#include <apr_lib.h>
#include <apr_file_info.h>
#include "svn_io.h"
#include "svn_types.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_config.h"
#include "svn_hash.h"
#include "svn_private_config.h"
#include "private/svn_magic.h"
#ifdef SVN_HAVE_LIBMAGIC
#include <magic.h>
#endif
struct svn_magic__cookie_t {
#ifdef SVN_HAVE_LIBMAGIC
magic_t magic;
#else
char dummy;
#endif
};
#ifdef SVN_HAVE_LIBMAGIC
static apr_status_t
close_magic_cookie(void *baton)
{
svn_magic__cookie_t *mc = (svn_magic__cookie_t*)baton;
magic_close(mc->magic);
return APR_SUCCESS;
}
#endif
svn_error_t *
svn_magic__init(svn_magic__cookie_t **magic_cookie,
apr_hash_t *config,
apr_pool_t *result_pool)
{
svn_magic__cookie_t *mc = NULL;
#ifdef SVN_HAVE_LIBMAGIC
if (config)
{
svn_boolean_t enable;
svn_config_t *cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
SVN_ERR(svn_config_get_bool(cfg, &enable,
SVN_CONFIG_SECTION_MISCELLANY,
SVN_CONFIG_OPTION_ENABLE_MAGIC_FILE,
TRUE));
if (!enable)
{
*magic_cookie = NULL;
return SVN_NO_ERROR;
}
}
mc = apr_palloc(result_pool, sizeof(*mc));
#ifndef MAGIC_MIME_TYPE
mc->magic = magic_open(MAGIC_MIME | MAGIC_ERROR);
#else
mc->magic = magic_open(MAGIC_MIME_TYPE | MAGIC_ERROR);
#endif
if (mc->magic)
{
if (magic_load(mc->magic, NULL) == -1)
{
magic_close(mc->magic);
mc = NULL;
}
else
apr_pool_cleanup_register(result_pool, mc, close_magic_cookie,
apr_pool_cleanup_null);
}
#endif
*magic_cookie = mc;
return SVN_NO_ERROR;
}
svn_error_t *
svn_magic__detect_binary_mimetype(const char **mimetype,
const char *local_abspath,
svn_magic__cookie_t *magic_cookie,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *magic_mimetype = NULL;
#ifdef SVN_HAVE_LIBMAGIC
apr_finfo_t finfo;
SVN_ERR(svn_io_stat(&finfo, local_abspath, APR_FINFO_SIZE, scratch_pool));
if (finfo.size > 0)
{
magic_mimetype = magic_file(magic_cookie->magic, local_abspath);
if (magic_mimetype)
{
if (strncmp(magic_mimetype, "text/", 5) == 0)
magic_mimetype = NULL;
else
{
svn_error_t *err;
#ifndef MAGIC_MIME_TYPE
char *p;
p = strchr(magic_mimetype, ' ');
if (p)
*p = '\0';
#endif
err = svn_mime_type_validate(magic_mimetype, scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_BAD_MIME_TYPE)
{
svn_error_clear(err);
magic_mimetype = NULL;
}
else
return svn_error_trace(err);
}
else
{
magic_mimetype = apr_pstrdup(result_pool, magic_mimetype);
}
}
}
}
#endif
*mimetype = magic_mimetype;
return SVN_NO_ERROR;
}