From 2e085a0a0542f9e5d6b2daf001143f8b9503490a Mon Sep 17 00:00:00 2001 From: infirit Date: Thu, 20 Nov 2014 14:27:41 +0100 Subject: add support for magic based identification of files Based on FR commits: 7b23961d200e3545af3815a8eb40d6d31757024f f08945a652ae1365ad6bbc5e3dcc8709031b5faf b6104a74e66ceca98884a6f974485a96a83526a2 From: Saleem Abdulrasool --- src/fr-archive.c | 95 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 31 deletions(-) (limited to 'src/fr-archive.c') diff --git a/src/fr-archive.c b/src/fr-archive.c index ab3e417..c2d1db3 100644 --- a/src/fr-archive.c +++ b/src/fr-archive.c @@ -41,6 +41,10 @@ #include "fr-process.h" #include "main.h" +#if ENABLE_MAGIC +#include +#endif + #ifndef NCARGS #define NCARGS _POSIX_ARG_MAX #endif @@ -525,43 +529,72 @@ get_mime_type_from_content (GFile *file) static const char * get_mime_type_from_magic_numbers (GFile *file) { - static struct { - const char *mime_type; - const char *first_bytes; - int offset; - int len; - } sniffer_data [] = { - /* Magic numbers taken from magic/Magdir/archive from the - * file-4.21 tarball. */ - { "application/x-7z-compressed", "7z\274\257\047\034", 0, 5 }, - { "application/x-ace", "**ACE**", 7, 7 }, - { "application/x-arj", "\x60\xea", 0, 2 }, - { "application/x-bzip2", "BZh", 0, 3 }, - { "application/x-gzip", "\037\213", 0, 2 }, - { "application/x-lzip", "LZIP", 0, 4 }, - { "application/x-lzop", "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 0, 9 }, - { "application/x-rar", "Rar!", 0, 4 }, - { "application/x-rzip", "RZIP", 0, 4 }, - { "application/x-xz", "\3757zXZ\000", 0, 6 }, - { "application/x-zoo", "\xdc\xa7\xc4\xfd", 20, 4 }, - { "application/zip", "PK\003\004", 0, 4 }, - { "application/zip", "PK00PK\003\004", 0, 8 }, - { "application/x-lrzip", "LRZI", 0, 4 }, - { NULL, NULL, 0 } +#if ENABLE_MAGIC + static magic_t magic = NULL; + + if (! magic) { + magic = magic_open (MAGIC_MIME_TYPE); + if (magic) + magic_load (magic, NULL); + else + g_warning ("unable to open magic database"); + } + + if (magic) { + const char * mime_type = NULL; + char * filepath = g_file_get_path (file); + + if (filepath) { + mime_type = magic_file (magic, filepath); + g_free (filepath); + } + + if (mime_type) + return mime_type; + + g_warning ("unable to detect filetype from magic: %s", + magic_error (magic)); + } +#else + static const struct magic { + const unsigned int off; + const unsigned int len; + const char * const id; + const char * const mime_type; + } magic_ids [] = { + /* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */ + { 0, 6, "7z\274\257\047\034", "application/x-7z-compressed" }, + { 7, 7, "**ACE**", "application/x-ace" }, + { 0, 2, "\x60\xea", "application/x-arj" }, + { 0, 3, "BZh", "application/x-bzip2" }, + { 0, 2, "\037\213", "application/x-gzip" }, + { 0, 4, "LZIP", "application/x-lzip" }, + { 0, 9, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", "application/x-lzop", }, + { 0, 4, "Rar!", "application/x-rar" }, + { 0, 4, "RZIP", "application/x-rzip" }, + { 0, 6, "\3757zXZ\000", "application/x-xz" }, + { 20, 4, "\xdc\xa7\xc4\xfd", "application/x-zoo", }, + { 0, 4, "PK\003\004", "application/zip" }, + { 0, 8, "PK00PK\003\004", "application/zip" }, + { 0, 4, "LRZI", "application/x-lrzip" }, }; + char buffer[32]; int i; - if (! g_load_file_in_buffer (file, buffer, 32, NULL)) + if (! g_load_file_in_buffer (file, buffer, sizeof (buffer), NULL)) return NULL; - for (i = 0; sniffer_data[i].mime_type != NULL; i++) - if (memcmp (sniffer_data[i].first_bytes, - buffer + sniffer_data[i].offset, - sniffer_data[i].len) == 0) - { - return sniffer_data[i].mime_type; - } + for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) { + const struct magic * const magic = &magic_ids[i]; + + if (sizeof (buffer) < (magic->off + magic->len)) + g_warning ("buffer underrun for mime type '%s' magic", + magic->mime_type); + else if (! memcmp (buffer + magic->off, magic->id, magic->len)) + return magic->mime_type; + } +#endif return NULL; } -- cgit v1.2.1