From a38892ff3b75c411ba7917412f6861d420cf9ae1 Mon Sep 17 00:00:00 2001 From: Arnavion Date: Wed, 20 Aug 2014 12:50:08 -0700 Subject: [PATCH] Use GFile API in gtkutil_check_file instead of stat/access. The latter functions expect codepage-encoded filenames on Windows but GLib's API returns filesystem-encoded paths, which on Windows are UTF-8. GLib API should be used to deal with GLib API results. Also fixed leaks in two of the callers of gtkutil_check_file() Fixes #968 --- src/fe-gtk/gtkutil.c | 74 +++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c index 50a85e2f..eabe9c75 100644 --- a/src/fe-gtk/gtkutil.c +++ b/src/fe-gtk/gtkutil.c @@ -66,48 +66,69 @@ gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq) } static void -gtkutil_check_file (char *file, struct file_req *freq) +gtkutil_check_file (char *filename, struct file_req *freq) { - struct stat st; int axs = FALSE; - char temp[256]; - path_part (file, temp, sizeof (temp)); + GFile *file = g_file_new_for_path (filename); - /* check if the file is readable or writable */ if (freq->flags & FRF_WRITE) { - if (access (temp, W_OK) == 0) - axs = TRUE; - } else - { - if (stat (file, &st) != -1) + GFile *parent = g_file_get_parent (file); + + GFileInfo *fi = g_file_query_info (parent, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (fi != NULL) { - if (!S_ISDIR (st.st_mode) || (freq->flags & FRF_CHOOSEFOLDER)) + if (g_file_info_get_attribute_boolean (fi, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) + { axs = TRUE; + } + + g_object_unref (fi); + } + + g_object_unref (parent); + } + else + { + GFileInfo *fi = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL); + + if (fi != NULL) + { + if (g_file_info_get_file_type (fi) != G_FILE_TYPE_DIRECTORY || (freq->flags & FRF_CHOOSEFOLDER)) + { + axs = TRUE; + } + + g_object_unref (fi); } } + g_object_unref (file); + if (axs) { - char *utf8_file; - /* convert to UTF8. It might be converted back to locale by - server.c's g_convert */ - utf8_file = hexchat_filename_to_utf8 (file, -1, NULL, NULL, NULL); - if (utf8_file) + char *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); + if (filename_utf8 != NULL) { - freq->callback (freq->userdata, utf8_file); - g_free (utf8_file); - } else + freq->callback (freq->userdata, filename_utf8); + g_free (filename_utf8); + } + else { fe_message ("Filename encoding is corrupt.", FE_MSG_ERROR); } - } else + } + else { if (freq->flags & FRF_WRITE) + { fe_message (_("Cannot write to that file."), FE_MSG_ERROR); + } else + { fe_message (_("Cannot read that file."), FE_MSG_ERROR); + } } } @@ -128,12 +149,21 @@ gtkutil_file_req_done (GtkWidget * wid, struct file_req *freq) } if (files) g_slist_free (files); - } else + } + else { if (freq->flags & FRF_CHOOSEFOLDER) - gtkutil_check_file (gtk_file_chooser_get_current_folder (fs), freq); + { + gchar *filename = gtk_file_chooser_get_current_folder (fs); + gtkutil_check_file (filename, freq); + g_free (filename); + } else + { + gchar *filename = gtk_file_chooser_get_filename (fs); gtkutil_check_file (gtk_file_chooser_get_filename (fs), freq); + g_free (filename); + } } /* this should call the "destroy" cb, where we free(freq) */