changeset 2297:4d0008b449d6

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.
author Colin Clark <cclark@mcb.net>
date Tue, 26 Apr 2016 15:52:12 +0100
parents a987ea1ea4f8
children 5256cfa521f6
files src/ui_bookmark.c src/uri_utils.c src/uri_utils.h
diffstat 3 files changed, 69 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/ui_bookmark.c	Thu Apr 14 14:25:44 2016 +0100
+++ b/src/ui_bookmark.c	Tue Apr 26 15:52:12 2016 +0100
@@ -707,13 +707,19 @@
 {
 	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;
--- a/src/uri_utils.c	Thu Apr 14 14:25:44 2016 +0100
+++ b/src/uri_utils.c	Tue Apr 26 15:52:12 2016 +0100
@@ -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 @@
 	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_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;
 }
--- a/src/uri_utils.h	Thu Apr 14 14:25:44 2016 +0100
+++ b/src/uri_utils.h	Tue Apr 26 15:52:12 2016 +0100
@@ -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);