From 5021767a18e06ad7a154e0b002a738c6ff119159 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Tue, 14 Jan 2014 18:01:34 +0100 Subject: [PATCH] Split of guess_content_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … and use it everywhere we want to get the content type of a file. Signed-off-by: Sebastian Ramacher --- content-type.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++ content-type.h | 8 +++ dbus-interface.c | 6 +- document.c | 167 +-------------------------------------------- synctex.c | 6 +- utils.c | 4 +- zathura.c | 5 +- 7 files changed, 191 insertions(+), 178 deletions(-) create mode 100644 content-type.c create mode 100644 content-type.h diff --git a/content-type.c b/content-type.c new file mode 100644 index 0000000..35b7a90 --- /dev/null +++ b/content-type.c @@ -0,0 +1,173 @@ +/* See LICENSE file for license and copyright information */ + +#define _BSD_SOURCE +#define _XOPEN_SOURCE 700 + +#include "content-type.h" +#include "macros.h" + +#include +#ifdef WITH_MAGIC +#include +#else +#include +#include +#endif +#include +#include +#include + +/** Read a most GT_MAX_READ bytes before falling back to file. */ +static const size_t GT_MAX_READ = 1 << 16; + +#ifdef WITH_MAGIC +static const char* +guess_type_magic(const char* path) { + const char* mime_type = NULL; + + /* creat magic cookie */ + const int flags = + MAGIC_MIME_TYPE | + MAGIC_SYMLINK | + MAGIC_NO_CHECK_APPTYPE | + MAGIC_NO_CHECK_CDF | + MAGIC_NO_CHECK_ELF | + MAGIC_NO_CHECK_ENCODING; + magic_t magic = magic_open(flags); + if (magic == NULL) { + girara_debug("failed creating the magic cookie"); + goto cleanup; + } + + /* ... and load mime database */ + if (magic_load(magic, NULL) < 0) { + girara_debug("failed loading the magic database: %s", magic_error(magic)); + goto cleanup; + } + + /* get the mime type */ + mime_type = magic_file(magic, path); + if (mime_type == NULL) { + girara_debug("failed guessing filetype: %s", magic_error(magic)); + goto cleanup; + } + /* dup so we own the memory */ + mime_type = g_strdup(mime_type); + + girara_debug("magic detected filetype: %s", mime_type); + +cleanup: + if (magic != NULL) { + magic_close(magic); + } + + return mime_type; +} + +static const char* +guess_type_file(const char* UNUSED(path)) +{ + return NULL; +} +#else +static const char* +guess_type_magic(const char* UNUSED(path)) { + return NULL; +} + +static const char* +guess_type_file(const char* path) +{ + GString* command = g_string_new("file -b --mime-type "); + char* tmp = g_shell_quote(path); + + g_string_append(command, tmp); + g_free(tmp); + + GError* error = NULL; + char* out = NULL; + int ret = 0; + g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error); + g_string_free(command, TRUE); + if (error != NULL) { + girara_warning("failed to execute command: %s", error->message); + g_error_free(error); + g_free(out); + return NULL; + } + if (WEXITSTATUS(ret) != 0) { + girara_warning("file failed with error code: %d", WEXITSTATUS(ret)); + g_free(out); + return NULL; + } + + g_strdelimit(out, "\n\r", '\0'); + return out; +} +#endif + +static const char* +guess_type_glib(const char* path) +{ + gboolean uncertain = FALSE; + const char* content_type = g_content_type_guess(path, NULL, 0, &uncertain); + if (content_type == NULL) { + girara_debug("g_content_type failed\n"); + } else { + if (uncertain == FALSE) { + girara_debug("g_content_type detected filetype: %s", content_type); + return content_type; + } + girara_debug("g_content_type is uncertain, guess: %s", content_type); + } + + FILE* f = fopen(path, "rb"); + if (f == NULL) { + return NULL; + } + + const int fd = fileno(f); + guchar* content = NULL; + size_t length = 0u; + ssize_t bytes_read = -1; + while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) { + g_free((void*)content_type); + content_type = NULL; + + content = g_realloc(content, length + BUFSIZ); + bytes_read = read(fd, content + length, BUFSIZ); + if (bytes_read == -1) { + break; + } + + length += bytes_read; + content_type = g_content_type_guess(NULL, content, length, &uncertain); + girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length); + } + + fclose(f); + g_free(content); + if (uncertain == FALSE) { + return content_type; + } + + g_free((void*)content_type); + return NULL; +} + +const char* +guess_content_type(const char* path) +{ + /* try libmagic first */ + const char* content_type = guess_type_magic(path); + if (content_type != NULL) { + return content_type; + } + /* else fallback to g_content_type_guess method */ + content_type = guess_type_glib(path); + if (content_type != NULL) { + return content_type; + } + /* and if libmagic is not available, try file as last resort */ + return guess_type_file(path); +} diff --git a/content-type.h b/content-type.h new file mode 100644 index 0000000..cb6beb2 --- /dev/null +++ b/content-type.h @@ -0,0 +1,8 @@ +/* See LICENSE file for license and copyright information */ + +#ifndef ZATHURA_CONTENT_TYPE_H +#define ZATHURA_CONTENT_TYPE_H + +const char* guess_content_type(const char* path); + +#endif diff --git a/dbus-interface.c b/dbus-interface.c index 0ddfc9c..38745d5 100644 --- a/dbus-interface.c +++ b/dbus-interface.c @@ -158,7 +158,7 @@ highlight_rects(zathura_t* zathura, unsigned int page, const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); for (unsigned int p = 0; p != number_of_pages; ++p) { - GObject* widget = G_OBJECT(priv->zathura->pages[p]); + GObject* widget = G_OBJECT(zathura->pages[p]); g_object_set(widget, "draw-links", FALSE, "search-results", rectangles[p], NULL); @@ -255,7 +255,7 @@ handle_method_call(GDBusConnection* UNUSED(connection), while (g_variant_iter_loop(iter, "(dddd)", &temp_rect.x1, &temp_rect.x2, &temp_rect.y1, &temp_rect.y2)) { zathura_rectangle_t* rect = g_malloc0(sizeof(zathura_rectangle_t)); - memcpy(rect, &temp_rect, sizeof(zathura_rectangle_t)); + *rect = temp_rect; girara_list_append(rectangles[page - 1], rect); } g_variant_iter_free(iter); @@ -274,7 +274,7 @@ handle_method_call(GDBusConnection* UNUSED(connection), } zathura_rectangle_t* rect = g_malloc0(sizeof(zathura_rectangle_t)); - memcpy(rect, &temp_rect, sizeof(zathura_rectangle_t)); + *rect = temp_rect; girara_list_append(rectangles[temp_page], rect); } g_variant_iter_free(secondary_iter); diff --git a/document.c b/document.c index 0e52e7e..c68aa37 100644 --- a/document.c +++ b/document.c @@ -3,18 +3,11 @@ #define _BSD_SOURCE #define _XOPEN_SOURCE 700 -#include #include #include #include #include -#include #include -#include -#ifdef WITH_MAGIC -#include -#endif -#include #include #include @@ -30,11 +23,7 @@ #include "database.h" #include "page.h" #include "plugin.h" - -/** Read a most GT_MAX_READ bytes before falling back to file. */ -static const size_t GT_MAX_READ = 1 << 16; - -static const char* guess_type(const char* path); +#include "content-type.h" /** * Document @@ -85,7 +74,7 @@ zathura_document_open(zathura_plugin_manager_t* plugin_manager, const char* return NULL; } - const char* content_type = guess_type(path); + const char* content_type = guess_content_type(path); if (content_type == NULL) { girara_error("Could not determine file type."); return NULL; @@ -664,158 +653,6 @@ zathura_document_get_information(zathura_document_t* document, zathura_error_t* return result; } -#ifdef WITH_MAGIC -static const char* -guess_type_magic(const char* path) { - const char* mime_type = NULL; - - /* creat magic cookie */ - const int flags = - MAGIC_MIME_TYPE | - MAGIC_SYMLINK | - MAGIC_NO_CHECK_APPTYPE | - MAGIC_NO_CHECK_CDF | - MAGIC_NO_CHECK_ELF | - MAGIC_NO_CHECK_ENCODING; - magic_t magic = magic_open(flags); - if (magic == NULL) { - girara_debug("failed creating the magic cookie"); - goto cleanup; - } - - /* ... and load mime database */ - if (magic_load(magic, NULL) < 0) { - girara_debug("failed loading the magic database: %s", magic_error(magic)); - goto cleanup; - } - - /* get the mime type */ - mime_type = magic_file(magic, path); - if (mime_type == NULL) { - girara_debug("failed guessing filetype: %s", magic_error(magic)); - goto cleanup; - } - /* dup so we own the memory */ - mime_type = g_strdup(mime_type); - - girara_debug("magic detected filetype: %s", mime_type); - -cleanup: - if (magic != NULL) { - magic_close(magic); - } - - return mime_type; -} - -static const char* -guess_type_file(const char* UNUSED(path)) -{ - return NULL; -} -#else -static const char* -guess_type_magic(const char* UNUSED(path)) { - return NULL; -} - -static const char* -guess_type_file(const char* path) -{ - GString* command = g_string_new("file -b --mime-type "); - char* tmp = g_shell_quote(path); - - g_string_append(command, tmp); - g_free(tmp); - - GError* error = NULL; - char* out = NULL; - int ret = 0; - g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error); - g_string_free(command, TRUE); - if (error != NULL) { - girara_warning("failed to execute command: %s", error->message); - g_error_free(error); - g_free(out); - return NULL; - } - if (WEXITSTATUS(ret) != 0) { - girara_warning("file failed with error code: %d", WEXITSTATUS(ret)); - g_free(out); - return NULL; - } - - g_strdelimit(out, "\n\r", '\0'); - return out; -} -#endif - -static const char* -guess_type_glib(const char* path) -{ - gboolean uncertain = FALSE; - const char* content_type = g_content_type_guess(path, NULL, 0, &uncertain); - if (content_type == NULL) { - girara_debug("g_content_type failed\n"); - } else { - if (uncertain == FALSE) { - girara_debug("g_content_type detected filetype: %s", content_type); - return content_type; - } - girara_debug("g_content_type is uncertain, guess: %s", content_type); - } - - FILE* f = fopen(path, "rb"); - if (f == NULL) { - return NULL; - } - - const int fd = fileno(f); - guchar* content = NULL; - size_t length = 0u; - ssize_t bytes_read = -1; - while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) { - g_free((void*)content_type); - content_type = NULL; - - content = g_realloc(content, length + BUFSIZ); - bytes_read = read(fd, content + length, BUFSIZ); - if (bytes_read == -1) { - break; - } - - length += bytes_read; - content_type = g_content_type_guess(NULL, content, length, &uncertain); - girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length); - } - - fclose(f); - g_free(content); - if (uncertain == FALSE) { - return content_type; - } - - g_free((void*)content_type); - return NULL; -} - -static const char* -guess_type(const char* path) -{ - /* try libmagic first */ - const char* content_type = guess_type_magic(path); - if (content_type != NULL) { - return content_type; - } - /* else fallback to g_content_type_guess method */ - content_type = guess_type_glib(path); - if (content_type != NULL) { - return content_type; - } - /* and if libmagic is not available, try file as last resort */ - return guess_type_file(path); -} - zathura_plugin_t* zathura_document_get_plugin(zathura_document_t* document) { diff --git a/synctex.c b/synctex.c index cb8b52b..d4a7cb9 100644 --- a/synctex.c +++ b/synctex.c @@ -1,10 +1,8 @@ /* See LICENSE file for license and copyright information */ #include -#include #include "synctex.h" - #include "zathura.h" #include "page.h" #include "document.h" @@ -181,7 +179,7 @@ synctex_rectangles_from_position(const char* filename, const char* position, } else if (rectangle != NULL) { synctex_page_rect_t* page_rect = g_malloc0(sizeof(synctex_page_rect_t)); page_rect->page = current_page; - memcpy(&page_rect->rect, rectangle, sizeof(zathura_rectangle_t)); + page_rect->rect = *rectangle; girara_list_append(other_rects, page_rect); } @@ -219,7 +217,7 @@ synctex_rectangles_from_position(const char* filename, const char* position, } else { synctex_page_rect_t* page_rect = g_malloc0(sizeof(synctex_page_rect_t)); page_rect->page = current_page; - memcpy(&page_rect->rect, rectangle, sizeof(zathura_rectangle_t)); + page_rect->rect = *rectangle; girara_list_append(other_rects, page_rect); g_free(rectangle); } diff --git a/utils.c b/utils.c index 382f3c4..c83c6b7 100644 --- a/utils.c +++ b/utils.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "links.h" #include "utils.h" @@ -22,6 +21,7 @@ #include "document.h" #include "page.h" #include "plugin.h" +#include "content-type.h" bool file_valid_extension(zathura_t* zathura, const char* path) @@ -30,7 +30,7 @@ file_valid_extension(zathura_t* zathura, const char* path) return false; } - const gchar* content_type = g_content_type_guess(path, NULL, 0, NULL); + const gchar* content_type = guess_content_type(path); if (content_type == NULL) { return false; } diff --git a/zathura.c b/zathura.c index 54777bc..1f5f4fd 100644 --- a/zathura.c +++ b/zathura.c @@ -1074,7 +1074,7 @@ bool position_set(zathura_t* zathura, double position_x, double position_y) { if (zathura == NULL || zathura->document == NULL) { - goto error_out; + return false; } double comppos_x, comppos_y; @@ -1113,9 +1113,6 @@ position_set(zathura_t* zathura, double position_x, double position_y) refresh_view(zathura); return true; - -error_out: - return false; }