[file-roller] fixed crash when the package installer is activated
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller] fixed crash when the package installer is activated
- Date: Fri, 28 Sep 2012 11:17:29 +0000 (UTC)
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]