OSX: Use xdgmime system to guess content type from data

Closes: Bug #788401

The problem is described here:

https://bugzilla.gnome.org/show_bug.cgi?id=788401

This patch introduces the use of the xdgmime system to guess
the content type from data. So you can guess for example the
type public.svg-image from the file content of a svg file.
This patch only applies to MacOS. A test for the regression
is also included.
This commit is contained in:
Friedrich Beckmann 2017-10-11 15:59:16 +02:00 committed by Philip Withnall
parent 13c6d9fedf
commit e55efa35e3
3 changed files with 45 additions and 8 deletions

View File

@ -3,10 +3,8 @@ include $(top_srcdir)/glib.mk
SUBDIRS = gdbus-2.0/codegen
if OS_UNIX
if !OS_COCOA
SUBDIRS += xdgmime
endif
endif
if OS_WIN32_AND_DLL_COMPILATION
if MS_LIB_AVAILABLE
@ -262,10 +260,9 @@ SUBDIRS += fam
endif
if OS_UNIX
if !OS_COCOA
platform_libadd += xdgmime/libxdgmime.la
platform_deps += xdgmime/libxdgmime.la
if !OS_COCOA
appinfo_headers += gdesktopappinfo.h
endif

View File

@ -25,6 +25,12 @@
#include <CoreServices/CoreServices.h>
#define XDG_PREFIX _gio_xdg
#include "xdgmime/xdgmime.h"
/* We lock this mutex whenever we modify global state in this module. */
G_LOCK_DEFINE_STATIC (gio_xdgmime);
/*< internal >
* create_cfstring_from_cstr:
@ -429,7 +435,17 @@ g_content_type_guess (const gchar *filename,
if (data && (!filename || !uti ||
CFStringCompare (uti, CFSTR ("public.data"), 0) == kCFCompareEqualTo))
{
if (looks_like_text (data, data_size))
const char *sniffed_mimetype;
G_LOCK (gio_xdgmime);
sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, NULL);
G_UNLOCK (gio_xdgmime);
if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN)
{
gchar *uti_str = g_content_type_from_mime_type (sniffed_mimetype);
uti = create_cfstring_from_cstr (uti_str);
g_free (uti_str);
}
if (!uti && looks_like_text (data, data_size))
{
if (g_str_has_prefix ((const gchar*)data, "#!/"))
uti = CFStringCreateCopy (NULL, CFSTR ("public.script"));

View File

@ -56,6 +56,8 @@ test_guess (void)
g_free (res);
g_free (expected);
/* Sadly OSX just doesn't have as large and robust of a mime type database as Linux */
#ifndef __APPLE__
res = g_content_type_guess ("foo", data, sizeof (data) - 1, &uncertain);
expected = g_content_type_from_mime_type ("text/plain");
g_assert_content_type_equals (expected, res);
@ -63,8 +65,6 @@ test_guess (void)
g_free (res);
g_free (expected);
/* Sadly OSX just doesn't have as large and robust of a mime type database as Linux */
#ifndef __APPLE__
res = g_content_type_guess ("foo.desktop", data, sizeof (data) - 1, &uncertain);
expected = g_content_type_from_mime_type ("application/x-desktop");
g_assert_content_type_equals (expected, res);
@ -110,6 +110,7 @@ test_guess (void)
g_assert (!uncertain);
g_free (res);
g_free (expected);
#endif
res = g_content_type_guess (NULL, (guchar *)"%!PS-Adobe-2.0 EPSF-1.2", 23, &uncertain);
expected = g_content_type_from_mime_type ("image/x-eps");
@ -117,7 +118,6 @@ test_guess (void)
g_assert (!uncertain);
g_free (res);
g_free (expected);
#endif
}
static void
@ -338,6 +338,29 @@ test_type_is_a_special_case (void)
g_assert_true (res);
}
static void
test_guess_svg_from_data (void)
{
const gchar svgfilecontent[] = "<svg xmlns=\"http://www.w3.org/2000/svg\"\
xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\
<rect x=\"10\" y=\"10\" height=\"100\" width=\"100\"\n\
style=\"stroke:#ff0000; fill: #0000ff\"/>\n\
</svg>\n";
gboolean uncertain = TRUE;
gchar *res = g_content_type_guess (NULL, (guchar *)svgfilecontent,
sizeof (svgfilecontent) - 1, &uncertain);
#ifdef __APPLE__
g_assert_cmpstr (res, ==, "public.svg-image");
#elif defined(G_OS_WIN32)
g_test_skip ("svg type detection from content is not implemented on WIN32");
#else
g_assert_cmpstr (res, ==, "image/svg+xml");
#endif
g_assert_false (uncertain);
g_free (res);
}
int
main (int argc, char *argv[])
{
@ -346,6 +369,7 @@ main (int argc, char *argv[])
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/contenttype/guess", test_guess);
g_test_add_func ("/contenttype/guess_svg_from_data", test_guess_svg_from_data);
g_test_add_func ("/contenttype/unknown", test_unknown);
g_test_add_func ("/contenttype/subtype", test_subtype);
g_test_add_func ("/contenttype/list", test_list);