From c6633ff42b46ec42d6757df147280c1f6f872260 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Tue, 26 Apr 2016 15:52:12 +0100 Subject: [PATCH] Fix crash on drag and drop from Xfe The issue is that when dragging and dropping from Xfe, paths aren't escaped like they are when dnd'ing from a GTK app. --- src/ui_bookmark.c | 8 +++++- src/uri_utils.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- src/uri_utils.h | 5 ++-- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/ui_bookmark.c b/src/ui_bookmark.c index 842b9479..18f73111 100644 --- a/src/ui_bookmark.c +++ b/src/ui_bookmark.c @@ -707,13 +707,19 @@ static void bookmark_dnd_get_data(GtkWidget *widget, { BookMarkData *bm = data; GList *list = NULL; + GList *errors = NULL; GList *work; gchar **uris; if (!bm->editable) return; uris = gtk_selection_data_get_uris(selection_data); - list = uri_filelist_from_uris(uris); + list = uri_filelist_from_uris(uris, &errors); + if(errors) + { + warning_dialog_dnd_uri_error(errors); + string_list_free(errors); + } g_strfreev(uris); work = list; diff --git a/src/uri_utils.c b/src/uri_utils.c index a60e4929..ceec7569 100644 --- a/src/uri_utils.c +++ b/src/uri_utils.c @@ -15,6 +15,26 @@ #include "filedata.h" #include "ui_fileops.h" +#include "ui_utildlg.h" + +void warning_dialog_dnd_uri_error(GList *uri_error_list) +{ + GList *work = uri_error_list; + guint count = g_list_length(work); + gchar *msg = g_strdup_printf("Failed to convert %d dropped item(s) to files\n", count); + if(count < 10) + { + while (work) + { + gchar *prev = msg; + msg = g_strdup_printf("%s\n%s", prev, (gchar *)work->data); + work = work->next; + g_free(prev); + } + } + warning_dialog(_("Drag and Drop failed"), msg, GTK_STOCK_DIALOG_WARNING, NULL); + g_free(msg); +} gchar **uris_from_pathlist(GList *list) { @@ -62,28 +82,54 @@ gboolean uri_selection_data_set_uris_from_filelist(GtkSelectionData *selection_d return ret; } -GList *uri_pathlist_from_uris(gchar **uris) +GList *uri_pathlist_from_uris(gchar **uris, GList **uri_error_list) { GList *list = NULL; guint i = 0; + GError *error = NULL; while (uris[i]) { - gchar *local_path = g_filename_from_uri(uris[i], NULL, NULL); + gchar *local_path = g_filename_from_uri(uris[i], NULL, &error); + if (error) + { + DEBUG_1("g_filename_from_uri failed on uri \"%s\"", uris[i]); + DEBUG_1(" error %d: %s", error->code, error->message); + if (error->code == G_CONVERT_ERROR_BAD_URI) + { + GError *retry_error = NULL; + gchar *escaped = g_uri_escape_string(uris[i], ":/", TRUE); + local_path = g_filename_from_uri(escaped, NULL, &retry_error); + if(retry_error) + { + DEBUG_1("manually escaped uri \"%s\" also failed g_filename_from_uri", escaped); + DEBUG_1(" error %d: %s", retry_error->code, retry_error->message); + g_error_free(retry_error); + } + g_free(escaped); + } + g_error_free(error); + error = NULL; + if (!local_path) + { + *uri_error_list = g_list_prepend(*uri_error_list, g_strdup(uris[i])); + i++; + continue; + } + } gchar *path = path_to_utf8(local_path); g_free(local_path); list = g_list_prepend(list, path); i++; } + *uri_error_list = g_list_reverse(*uri_error_list); return g_list_reverse(list); } - - -GList *uri_filelist_from_uris(gchar **uris) +GList *uri_filelist_from_uris(gchar **uris, GList **uri_error_list) { - GList *path_list = uri_pathlist_from_uris(uris); + GList *path_list = uri_pathlist_from_uris(uris, uri_error_list); GList *filelist = filelist_from_path_list(path_list); string_list_free(path_list); return filelist; @@ -91,8 +137,14 @@ GList *uri_filelist_from_uris(gchar **uris) GList *uri_filelist_from_gtk_selection_data(GtkSelectionData *selection_data) { + GList *errors = NULL; gchar **uris = gtk_selection_data_get_uris(selection_data); - GList *ret = uri_filelist_from_uris(uris); + GList *ret = uri_filelist_from_uris(uris, &errors); + if(errors) + { + warning_dialog_dnd_uri_error(errors); + string_list_free(errors); + } g_strfreev(uris); return ret; } diff --git a/src/uri_utils.h b/src/uri_utils.h index 5c3139a5..b32328e5 100644 --- a/src/uri_utils.h +++ b/src/uri_utils.h @@ -12,10 +12,11 @@ #ifndef URI_UTILS_H #define URI_UTILS_H -GList *uri_filelist_from_uris(gchar **uris); +void warning_dialog_dnd_uri_error(GList *uri_error_list); +GList *uri_filelist_from_uris(gchar **uris, GList **uri_error_list); gchar **uris_from_pathlist(GList *list); gchar **uris_from_filelist(GList *list); -GList *uri_pathlist_from_uris(gchar **uris); +GList *uri_pathlist_from_uris(gchar **uris, GList **uri_error_list); gboolean uri_selection_data_set_uris_from_filelist(GtkSelectionData *selection_data, GList *list); GList *uri_filelist_from_gtk_selection_data(GtkSelectionData *selection_data); -- 2.20.1