Fix crash on drag and drop from Xfe
authorColin Clark <cclark@mcb.net>
Tue, 26 Apr 2016 14:52:12 +0000 (15:52 +0100)
committerColin Clark <cclark@mcb.net>
Tue, 26 Apr 2016 14:52:12 +0000 (15:52 +0100)
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
src/uri_utils.c
src/uri_utils.h

index 842b947..18f7311 100644 (file)
@@ -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;
index a60e492..ceec756 100644 (file)
 
 #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;
 }
index 5c3139a..b32328e 100644 (file)
 #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);