zathura/zathura/content-type.c
Sebastian Ramacher fbfbefe18b Remove unused code
2022-05-08 16:43:07 +02:00

167 lines
4.4 KiB
C

/* SPDX-License-Identifier: Zlib */
#include "content-type.h"
#include "macros.h"
#include <gio/gio.h>
#include <girara/utils.h>
#include <glib.h>
#include <magic.h>
#include <stdio.h>
struct zathura_content_type_context_s {
magic_t magic;
};
zathura_content_type_context_t*
zathura_content_type_new(void)
{
zathura_content_type_context_t* context = g_try_malloc0(sizeof(zathura_content_type_context_t));
if (context == NULL) {
return NULL;
}
/* creat magic cookie */
static const int flags = MAGIC_ERROR | 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");
return context;
}
/* ... and load mime database */
if (magic_load(magic, NULL) < 0) {
girara_debug("failed loading the magic database: %s", magic_error(magic));
magic_close(magic);
return context;
}
context->magic = magic;
return context;
}
void
zathura_content_type_free(zathura_content_type_context_t* context)
{
if (context != NULL && context->magic != NULL) {
magic_close(context->magic);
}
g_free(context);
}
/** Read a most GT_MAX_READ bytes before falling back to file. */
static const size_t GT_MAX_READ = 1 << 16;
static char*
guess_type_magic(zathura_content_type_context_t* context, const char* path)
{
if (context == NULL || context->magic == NULL) {
return NULL;
}
const char* mime_type = NULL;
/* get the mime type */
mime_type = magic_file(context->magic, path);
if (mime_type == NULL || magic_errno(context->magic) != 0) {
girara_debug("failed guessing filetype: %s", magic_error(context->magic));
return NULL;
}
girara_debug("magic detected filetype: %s", mime_type);
char* content_type = g_content_type_from_mime_type(mime_type);
if (content_type == NULL) {
girara_warning("failed to convert mime type to content type: %s", mime_type);
/* dup so we own the memory */
return g_strdup(mime_type);
}
return content_type;
}
static char*
guess_type_glib(const char* path)
{
gboolean uncertain = FALSE;
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;
}
guchar* content = NULL;
size_t length = 0;
while (uncertain == TRUE && length < GT_MAX_READ) {
g_free(content_type);
content_type = NULL;
guchar* temp_content = g_try_realloc(content, length + BUFSIZ);
if (temp_content == NULL) {
break;
}
content = temp_content;
size_t bytes_read = fread(content + length, 1, BUFSIZ, f);
if (bytes_read == 0) {
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(content_type);
return NULL;
}
static int
compare_content_types(const void* lhs, const void* rhs)
{
return g_strcmp0(lhs, rhs);
}
char*
zathura_content_type_guess(zathura_content_type_context_t* context, const char* path,
const girara_list_t* supported_content_types)
{
/* try libmagic first */
char* content_type = guess_type_magic(context, path);
if (content_type != NULL) {
if (supported_content_types == NULL ||
girara_list_find(supported_content_types, compare_content_types, content_type) != NULL) {
return content_type;
}
girara_debug("content type '%s' not supported, trying again", content_type);
g_free(content_type);
}
/* else fallback to g_content_type_guess method */
content_type = guess_type_glib(path);
if (content_type != NULL) {
if (supported_content_types == NULL ||
girara_list_find(supported_content_types, compare_content_types, content_type) != NULL) {
return content_type;
}
girara_debug("content type '%s' not supported", content_type);
g_free(content_type);
}
return NULL;
}