diff options
-rw-r--r-- | configure.ac | 33 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/fr-archive.c | 95 |
3 files changed, 102 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac index 68e1d47..8285bcc 100644 --- a/configure.ac +++ b/configure.ac @@ -164,6 +164,38 @@ fi dnl ****************************** +dnl ****************************** + +AC_ARG_ENABLE([magic], + AS_HELP_STRING([--enable-magic], [use libmagic to detect file type]),, + [enable_magic=no]) + +if test x"$enable_magic" = x"yes" ; then + save_LIBS="$LIBS" + LIBS="$LIBS -lmagic" + AC_MSG_CHECKING([whether libmagic works]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ +#include <magic.h> +int main () { magic_t m = magic_open(MAGIC_NONE); } +])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([libmagic is needed for magic])]) + LIBS="$save_LIBS" + + MAGIC_CFLAGS= + MAGIC_LIBS=-lmagic + + AC_SUBST(MAGIC_CFLAGS) + AC_SUBST(MAGIC_LIBS) + + AC_DEFINE(ENABLE_MAGIC, 1, [define to enable magic]) +fi + +AM_CONDITIONAL(ENABLE_MAGIC, test x"$enable_magic" != x"no") + +dnl ****************************** + YELP_HELP_INIT dnl ****************************** @@ -211,5 +243,6 @@ Configuration: Caja support: ${enable_caja_actions} PackageKit support: ${enable_packagekit} Run in place ${enable_run_in_place} + Use libmagic: ${enable_magic} JSON support: ${enable_json_glib} " diff --git a/src/Makefile.am b/src/Makefile.am index cba14ad..ef11ec3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -189,7 +189,11 @@ fr-enum-types.c: typedefs.h fr-enum-types.h engrampa_LDADD = \ $(top_builddir)/copy-n-paste/libeggsmclient.la \ $(FR_LIBS) \ - ${JSON_GLIB_LIBS} + ${JSON_GLIB_LIBS} + +if ENABLE_MAGIC +engrampa_LDADD += $(MAGIC_LIBS) +endif EXTRA_DIST = fr-marshal.list 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 <magic.h> +#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; } |