[file-roller] fixed crash when the package installer is activated



commit b1455f95c65b81cb0027af4ffb9b2586a86c2bcb
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Fri Sep 28 11:34:16 2012 +0200

    fixed crash when the package installer is activated
    
    [bug #684941]

 src/dlg-package-installer.c |   92 +++++++++++++++++------
 src/dlg-package-installer.h |    7 +-
 src/fr-archive.c            |   97 +----------------------
 src/fr-init.c               |   20 +++++-
 src/fr-init.h               |    3 +-
 src/fr-window.c             |    5 +-
 src/gio-utils.c             |  176 +++++++++++++++++++++++++++++++++++++++++++
 src/gio-utils.h             |   10 +++
 src/glib-utils.c            |   69 +++++++++++++++++
 src/glib-utils.h            |    2 +
 10 files changed, 360 insertions(+), 121 deletions(-)
---
diff --git a/src/dlg-package-installer.c b/src/dlg-package-installer.c
index 4f4e281..6fa8b4c 100644
--- a/src/dlg-package-installer.c
+++ b/src/dlg-package-installer.c
@@ -25,23 +25,28 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include "dlg-package-installer.h"
+#include "gio-utils.h"
+#include "glib-utils.h"
 #include "gtk-utils.h"
 #include "fr-init.h"
 
 
+#define BUFFER_SIZE_FOR_PRELOAD 32
+
+
 typedef struct {
-	FrWindow   *window;
-	FrArchive  *archive;
-	FrAction    action;
-	const char *packages;
+	FrWindow     *window;
+	FrAction      action;
+	GCancellable *cancellable;
+	const char   *packages;
 } InstallerData;
 
 
 static void
 installer_data_free (InstallerData *idata)
 {
-	g_object_unref (idata->archive);
 	g_object_unref (idata->window);
+	_g_object_ref (idata->cancellable);
 	g_free (idata);
 }
 
@@ -159,7 +164,7 @@ install_packages (InstallerData *idata)
 	GDBusConnection *connection;
 	GError          *error = NULL;
 
-	connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+	connection = g_bus_get_sync (G_BUS_TYPE_SESSION, idata->cancellable, &error);
 	if (connection != NULL) {
 		GdkWindow  *window;
 		GDBusProxy *proxy;
@@ -180,7 +185,7 @@ install_packages (InstallerData *idata)
 					       "org.freedesktop.PackageKit",
 					       "/org/freedesktop/PackageKit",
 					       "org.freedesktop.PackageKit.Modify",
-					       NULL,
+					       idata->cancellable,
 					       &error);
 
 		if (proxy != NULL) {
@@ -204,7 +209,7 @@ install_packages (InstallerData *idata)
 							  "hide-confirm-search,hide-finished,hide-warning"),
 					   G_DBUS_CALL_FLAGS_NONE,
 					   G_MAXINT,
-					   NULL,
+					   idata->cancellable,
 					   packagekit_install_package_names_ready_cb,
 					   idata);
 
@@ -248,30 +253,50 @@ confirm_search_dialog_response_cb (GtkDialog *dialog,
 #endif /* ENABLE_PACKAGEKIT */
 
 
-void
-dlg_package_installer (FrWindow  *window,
-		       FrArchive *archive,
-		       FrAction   action)
+static void
+file_buffer_ready_cb (GObject      *source_object,
+		      GAsyncResult *result,
+		      gpointer      user_data)
 {
-	InstallerData   *idata;
-	GType            archive_type;
-	FrArchive       *preferred_archive;
+	InstallerData *idata = user_data;
+	GFile         *file;
+	char          *buffer;
+	gsize          buffer_size;
+	GError        *error = NULL;
+	char          *uri;
+	const char    *mime_type;
+	gboolean       result_uncertain;
+	GType          archive_type;
+	FrArchive     *preferred_archive;
+
+	file = G_FILE (source_object);
+	if (! _g_file_load_buffer_finish (file, result, &buffer, &buffer_size, &error)) {
+		package_installer_terminated (idata, FR_ERROR_GENERIC, error->message);
+		g_error_free (error);
+		return;
+	}
 
-	idata = g_new0 (InstallerData, 1);
-	idata->window = g_object_ref (window);
-	idata->archive = g_object_ref (archive);
-	idata->action = action;
+	uri = g_file_get_uri (file);
+	mime_type = g_content_type_guess (uri, (guchar *) buffer, buffer_size, &result_uncertain);
+	if (result_uncertain) {
+		mime_type = _g_mime_type_get_from_content (buffer, buffer_size);
+		if (mime_type == NULL)
+			mime_type = _g_mime_type_get_from_filename (file);
+	}
 
-	archive_type = get_preferred_archive_for_mime_type (idata->archive->mime_type, FR_ARCHIVE_CAN_READ_WRITE);
+	g_free (uri);
+	g_free (buffer);
+
+	archive_type = get_preferred_archive_for_mime_type (mime_type, FR_ARCHIVE_CAN_READ_WRITE);
 	if (archive_type == 0)
-		archive_type = get_preferred_archive_for_mime_type (idata->archive->mime_type, FR_ARCHIVE_CAN_READ);
+		archive_type = get_preferred_archive_for_mime_type (mime_type, FR_ARCHIVE_CAN_READ);
 	if (archive_type == 0) {
 		package_installer_terminated (idata, FR_ERROR_GENERIC, _("Archive type not supported."));
 		return;
 	}
 
 	preferred_archive = g_object_new (archive_type, 0);
-	idata->packages = fr_archive_get_packages (preferred_archive, idata->archive->mime_type);
+	idata->packages = fr_archive_get_packages (preferred_archive, mime_type);
 	g_object_unref (preferred_archive);
 
 	if (idata->packages == NULL) {
@@ -286,7 +311,7 @@ dlg_package_installer (FrWindow  *window,
 		GtkWidget *dialog;
 
 		secondary_text = g_strdup_printf (_("There is no command installed for %s files.\nDo you want to search for a command to open this file?"),
-						  g_content_type_get_description (idata->archive->mime_type));
+						  g_content_type_get_description (mime_type));
 		dialog = _gtk_message_dialog_new (GTK_WINDOW (idata->window),
 						  GTK_DIALOG_MODAL,
 						  GTK_STOCK_DIALOG_ERROR,
@@ -307,3 +332,24 @@ dlg_package_installer (FrWindow  *window,
 
 #endif /* ENABLE_PACKAGEKIT */
 }
+
+
+void
+dlg_package_installer (FrWindow     *window,
+		       GFile        *file,
+		       FrAction      action,
+		       GCancellable *cancellable)
+{
+	InstallerData   *idata;
+
+	idata = g_new0 (InstallerData, 1);
+	idata->window = g_object_ref (window);
+	idata->action = action;
+	idata->cancellable = _g_object_ref (cancellable);
+
+	_g_file_load_buffer_async (file,
+				   BUFFER_SIZE_FOR_PRELOAD,
+				   cancellable,
+				   file_buffer_ready_cb,
+				   idata);
+}
diff --git a/src/dlg-package-installer.h b/src/dlg-package-installer.h
index 16405f4..c82ec0a 100644
--- a/src/dlg-package-installer.h
+++ b/src/dlg-package-installer.h
@@ -24,8 +24,9 @@
 
 #include "fr-window.h"
 
-void dlg_package_installer (FrWindow  *window,
-			    FrArchive *archive,
-			    FrAction   action);
+void dlg_package_installer (FrWindow     *window,
+			    GFile        *file,
+			    FrAction      action,
+			    GCancellable *cancellable);
 
 #endif /* DLG_PACKAGE_INSTALLER_H */
diff --git a/src/fr-archive.c b/src/fr-archive.c
index 25f09fc..c44be18 100644
--- a/src/fr-archive.c
+++ b/src/fr-archive.c
@@ -547,24 +547,6 @@ fr_archive_set_stoppable (FrArchive *archive,
 /* -- fr_archive_new_for_creating -- */
 
 
-static const char *
-get_mime_type_from_filename (GFile *file)
-{
-	const char *mime_type = NULL;
-	char       *uri;
-
-	if (file == NULL)
-		return NULL;
-
-	uri = g_file_get_uri (file);
-	mime_type = get_mime_type_from_extension (_g_filename_get_extension (uri));
-
-	g_free (uri);
-
-	return mime_type;
-}
-
-
 static FrArchive *
 create_archive_for_mime_type (GType          archive_type,
 			      GFile         *file,
@@ -599,7 +581,7 @@ fr_archive_create (GFile      *file,
 	GFile     *parent;
 
 	if (mime_type == NULL)
-		mime_type = get_mime_type_from_filename (file);
+		mime_type = _g_mime_type_get_from_filename (file);
 	archive_type = get_archive_type_from_mime_type (mime_type, FR_ARCHIVE_CAN_WRITE);
 
 	archive = create_archive_for_mime_type (archive_type,
@@ -659,75 +641,6 @@ open_data_complete_with_error (OpenData *load_data,
 }
 
 
-static const char *
-get_mime_type_from_magic_numbers (char  *buffer,
-				  gsize  buffer_size)
-{
-#if ENABLE_MAGIC
-
-	static magic_t magic = NULL;
-
-	if (magic == NULL) {
-		magic = magic_open (MAGIC_MIME_TYPE);
-		if (magic != NULL)
-			magic_load (magic, NULL);
-		else
-			g_warning ("unable to open magic database");
-	}
-
-	if (magic != NULL) {
-		const char * mime_type;
-
-		mime_type = magic_buffer (magic, buffer, buffer_size);
-		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"         },
-	};
-
-	int  i;
-
-	for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
-		const struct magic * const magic = &magic_ids[i];
-
-		if ((magic->off + magic->len) > buffer_size)
-			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;
-}
-
-
 static FrArchive *
 create_archive_to_load_archive (GFile      *file,
 			        const char *mime_type)
@@ -808,10 +721,10 @@ open_archive_stream_ready_cb (GObject      *source_object,
 		archive = create_archive_to_load_archive (open_data->file, mime_type);
 	}
 	if (archive == NULL) {
-		mime_type = get_mime_type_from_magic_numbers (open_data->buffer, open_data->buffer_size);
+		mime_type = _g_mime_type_get_from_content (open_data->buffer, open_data->buffer_size);
 		archive = create_archive_to_load_archive (open_data->file, mime_type);
 		if (archive == NULL) {
-			mime_type = get_mime_type_from_filename (open_data->file);
+			mime_type = _g_mime_type_get_from_filename (open_data->file);
 			archive = create_archive_to_load_archive (open_data->file, mime_type);
 			if (archive == NULL) {
 				error = g_error_new_literal (FR_ERROR,
@@ -2250,9 +2163,9 @@ _g_file_is_archive (GFile *file)
 		uri = g_file_get_uri (file);
 		mime_type = g_content_type_guess (uri, (guchar *) buffer, buffer_size, &result_uncertain);
 		if (result_uncertain) {
-			mime_type = get_mime_type_from_magic_numbers (buffer, buffer_size);
+			mime_type = _g_mime_type_get_from_content (buffer, buffer_size);
 			if (mime_type == NULL)
-				mime_type = get_mime_type_from_filename (file);
+				mime_type = _g_mime_type_get_from_filename (file);
 		}
 
 		if (mime_type != NULL) {
diff --git a/src/fr-init.c b/src/fr-init.c
index 8f0d022..f4a7c83 100644
--- a/src/fr-init.c
+++ b/src/fr-init.c
@@ -447,7 +447,7 @@ update_registered_archives_capabilities (void)
 
 
 const char *
-get_mime_type_from_extension (const char *ext)
+_g_mime_type_get_from_extension (const char *ext)
 {
 	int i;
 
@@ -466,6 +466,24 @@ get_mime_type_from_extension (const char *ext)
 
 
 const char *
+_g_mime_type_get_from_filename (GFile *file)
+{
+	const char *mime_type = NULL;
+	char       *uri;
+
+	if (file == NULL)
+		return NULL;
+
+	uri = g_file_get_uri (file);
+	mime_type = _g_mime_type_get_from_extension (_g_filename_get_extension (uri));
+
+	g_free (uri);
+
+	return mime_type;
+}
+
+
+const char *
 get_archive_filename_extension (const char *filename)
 {
 	const char *ext;
diff --git a/src/fr-init.h b/src/fr-init.h
index 1e88458..0de0c7c 100644
--- a/src/fr-init.h
+++ b/src/fr-init.h
@@ -62,7 +62,8 @@ GType        get_archive_type_from_mime_type         (const char    *mime_type,
 GType        get_preferred_archive_for_mime_type     (const char    *mime_type,
 						      FrArchiveCaps  requested_capabilities);
 void         update_registered_archives_capabilities (void);
-const char * get_mime_type_from_extension            (const char    *ext);
+const char * _g_mime_type_get_from_extension         (const char    *ext);
+const char * _g_mime_type_get_from_filename          (GFile         *file);
 const char * get_archive_filename_extension          (const char    *uri);
 int          get_mime_type_index                     (const char    *mime_type);
 void         sort_mime_types_by_extension            (int           *a);
diff --git a/src/fr-window.c b/src/fr-window.c
index e6f54a4..856e8d0 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -2776,7 +2776,10 @@ _handle_archive_operation_error (FrWindow  *window,
 
 	case FR_ERROR_UNSUPPORTED_FORMAT:
 		close_progress_dialog (window, TRUE);
-		dlg_package_installer (window, archive, action);
+		dlg_package_installer (window,
+				       window->priv->archive_file,
+				       action,
+				       window->priv->cancellable);
 		if (opens_dialog) *opens_dialog = TRUE;
 		break;
 
diff --git a/src/gio-utils.c b/src/gio-utils.c
index 1fd7a21..f8452f1 100644
--- a/src/gio-utils.c
+++ b/src/gio-utils.c
@@ -1306,3 +1306,179 @@ g_load_file_in_buffer (GFile   *file,
 	return (n >= 0);
 }
 
+
+/* -- _g_file_load_buffer_async -- */
+
+
+#define MAX_BUFFER_SIZE_FOR_TMP_BUFFER 4096
+
+
+typedef struct {
+	GFile              *file;
+	GCancellable       *cancellable;
+	GSimpleAsyncResult *result;
+        gsize               requested_buffer_size;
+	char               *buffer;
+        gchar              *tmp_buffer;
+        gsize               tmp_buffer_size;
+        GInputStream       *stream;
+        gsize               buffer_size;
+} LoadBufferData;
+
+
+static void
+load_buffer_data_free (LoadBufferData *load_data)
+{
+	_g_object_unref (load_data->file);
+	_g_object_unref (load_data->cancellable);
+	_g_object_unref (load_data->result);
+	g_free (load_data->buffer);
+	g_free (load_data->tmp_buffer);
+	_g_object_unref (load_data->stream);
+	g_free (load_data);
+}
+
+
+static void
+load_buffer_data_complete_with_error (LoadBufferData *load_data,
+				      GError         *error)
+{
+	GSimpleAsyncResult *result;
+
+	result = g_object_ref (load_data->result);
+	g_simple_async_result_set_from_error (result, error);
+	g_simple_async_result_complete_in_idle (result);
+
+	g_object_unref (result);
+}
+
+
+static void
+load_buffer_stream_read_ready_cb (GObject      *source_object,
+				  GAsyncResult *result,
+				  gpointer      user_data)
+{
+	LoadBufferData *load_data = user_data;
+        GError         *error = NULL;
+        gssize          count;
+
+        count = g_input_stream_read_finish (load_data->stream, result, &error);
+        if (count < 0) {
+        	load_buffer_data_complete_with_error (load_data, error);
+                return;
+        }
+
+        if (count > 0) {
+		load_data->buffer = g_realloc (load_data->buffer, load_data->buffer_size + count + 1);
+		memcpy (load_data->buffer + load_data->buffer_size, load_data->tmp_buffer, count);
+		load_data->buffer_size += count;
+        }
+
+        if ((count == 0) || ((load_data->requested_buffer_size > 0) && (load_data->buffer_size >= load_data->requested_buffer_size))) {
+                if (load_data->buffer != NULL)
+                        ((char *)load_data->buffer)[load_data->buffer_size] = 0;
+                g_simple_async_result_complete_in_idle (load_data->result);
+                return;
+        }
+
+        g_input_stream_read_async (load_data->stream,
+                                   load_data->tmp_buffer,
+                                   load_data->tmp_buffer_size,
+                                   G_PRIORITY_DEFAULT,
+                                   load_data->cancellable,
+                                   load_buffer_stream_read_ready_cb,
+                                   load_data);
+}
+
+
+static void
+load_buffer_read_ready_cb (GObject      *source_object,
+			   GAsyncResult *result,
+			   gpointer      user_data)
+{
+	LoadBufferData *load_data = user_data;
+        GError         *error = NULL;
+
+        load_data->stream = (GInputStream *) g_file_read_finish (G_FILE (source_object), result, &error);
+        if (load_data->stream == NULL) {
+        	load_buffer_data_complete_with_error (load_data, error);
+                return;
+        }
+
+        g_input_stream_read_async (load_data->stream,
+                                   load_data->tmp_buffer,
+                                   load_data->tmp_buffer_size,
+                                   G_PRIORITY_DEFAULT,
+                                   load_data->cancellable,
+                                   load_buffer_stream_read_ready_cb,
+                                   load_data);
+}
+
+
+void
+_g_file_load_buffer_async (GFile               *file,
+			   gsize                requested_size,
+			   GCancellable        *cancellable,
+			   GAsyncReadyCallback  callback,
+			   gpointer             user_data)
+{
+	LoadBufferData *load_data;
+
+	g_return_if_fail (file != NULL);
+
+	load_data = g_new0 (LoadBufferData, 1);
+	load_data->file = g_object_ref (file);
+	load_data->cancellable = _g_object_ref (cancellable);
+	load_data->result = g_simple_async_result_new (G_OBJECT (file),
+						       callback,
+						       user_data,
+						       _g_file_load_buffer_async);
+	load_data->requested_buffer_size = requested_size;
+	load_data->buffer = NULL;
+	load_data->buffer_size = 0;
+	if ((requested_size > 0) && (requested_size < MAX_BUFFER_SIZE_FOR_TMP_BUFFER))
+		load_data->tmp_buffer_size = requested_size;
+	else
+		load_data->tmp_buffer_size = MAX_BUFFER_SIZE_FOR_TMP_BUFFER;
+	load_data->tmp_buffer = g_new (char, load_data->tmp_buffer_size);
+        g_simple_async_result_set_op_res_gpointer (load_data->result,
+        					   load_data,
+                                                   (GDestroyNotify) load_buffer_data_free);
+
+        /* load a few bytes to guess the archive type */
+
+	g_file_read_async (load_data->file,
+			   G_PRIORITY_DEFAULT,
+			   load_data->cancellable,
+			   load_buffer_read_ready_cb,
+			   load_data);
+}
+
+
+gboolean
+_g_file_load_buffer_finish (GFile         *file,
+			    GAsyncResult  *result,
+			    char         **buffer,
+			    gsize         *buffer_size,
+			    GError       **error)
+{
+	GSimpleAsyncResult *simple;
+	LoadBufferData     *load_data;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (file), _g_file_load_buffer_async), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+
+	load_data = g_simple_async_result_get_op_res_gpointer (simple);
+	if (buffer != NULL) {
+		*buffer = load_data->buffer;
+		load_data->buffer = NULL;
+	}
+	if (buffer_size != NULL)
+		*buffer_size = load_data->buffer_size;
+
+	return TRUE;
+}
diff --git a/src/gio-utils.h b/src/gio-utils.h
index ee363af..f784c41 100644
--- a/src/gio-utils.h
+++ b/src/gio-utils.h
@@ -167,5 +167,15 @@ gboolean g_load_file_in_buffer       (GFile                 *file,
 				      void                  *buffer,
 				      gsize                  size,
 				      GError               **error);
+void     _g_file_load_buffer_async   (GFile                 *file,
+				      gsize                  requested_size,
+				      GCancellable          *cancellable,
+				      GAsyncReadyCallback    callback,
+				      gpointer               user_data);
+gboolean _g_file_load_buffer_finish  (GFile                 *file,
+				      GAsyncResult          *result,
+				      char                 **buffer,
+				      gsize                 *buffer_size,
+				      GError               **error);
 
 #endif /* _GIO_UTILS_H */
diff --git a/src/glib-utils.c b/src/glib-utils.c
index 8affc97..119edf4 100644
--- a/src/glib-utils.c
+++ b/src/glib-utils.c
@@ -1078,6 +1078,75 @@ _g_mime_type_matches (const char *mime_type,
 }
 
 
+const char *
+_g_mime_type_get_from_content (char  *buffer,
+			       gsize  buffer_size)
+{
+#if ENABLE_MAGIC
+
+	static magic_t magic = NULL;
+
+	if (magic == NULL) {
+		magic = magic_open (MAGIC_MIME_TYPE);
+		if (magic != NULL)
+			magic_load (magic, NULL);
+		else
+			g_warning ("unable to open magic database");
+	}
+
+	if (magic != NULL) {
+		const char * mime_type;
+
+		mime_type = magic_buffer (magic, buffer, buffer_size);
+		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"         },
+	};
+
+	int  i;
+
+	for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
+		const struct magic * const magic = &magic_ids[i];
+
+		if ((magic->off + magic->len) > buffer_size)
+			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;
+}
+
+
 /* GFile */
 
 
diff --git a/src/glib-utils.h b/src/glib-utils.h
index a69bc74..c409ea1 100644
--- a/src/glib-utils.h
+++ b/src/glib-utils.h
@@ -146,6 +146,8 @@ char *              _g_filename_get_random         (int                  random_
 						    const char          *suffix);
 gboolean            _g_mime_type_matches           (const char          *type,
 						    const char          *pattern);
+const char *        _g_mime_type_get_from_content  (char                *buffer,
+		  	  	  	  	    gsize                buffer_size);
 
 /* GFile */
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]