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
This commit is contained in:
Arnavion 2014-08-20 12:50:08 -07:00
parent dc18e3da07
commit a38892ff3b

View File

@ -66,48 +66,69 @@ gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq)
} }
static void 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; 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 (freq->flags & FRF_WRITE)
{ {
if (access (temp, W_OK) == 0) GFile *parent = g_file_get_parent (file);
axs = TRUE;
} else GFileInfo *fi = g_file_query_info (parent, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
{ if (fi != NULL)
if (stat (file, &st) != -1)
{ {
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; 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) if (axs)
{ {
char *utf8_file; char *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
/* convert to UTF8. It might be converted back to locale by if (filename_utf8 != NULL)
server.c's g_convert */
utf8_file = hexchat_filename_to_utf8 (file, -1, NULL, NULL, NULL);
if (utf8_file)
{ {
freq->callback (freq->userdata, utf8_file); freq->callback (freq->userdata, filename_utf8);
g_free (utf8_file); g_free (filename_utf8);
} else }
else
{ {
fe_message ("Filename encoding is corrupt.", FE_MSG_ERROR); fe_message ("Filename encoding is corrupt.", FE_MSG_ERROR);
} }
} else }
else
{ {
if (freq->flags & FRF_WRITE) if (freq->flags & FRF_WRITE)
{
fe_message (_("Cannot write to that file."), FE_MSG_ERROR); fe_message (_("Cannot write to that file."), FE_MSG_ERROR);
}
else else
{
fe_message (_("Cannot read that file."), FE_MSG_ERROR); 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) if (files)
g_slist_free (files); g_slist_free (files);
} else }
else
{ {
if (freq->flags & FRF_CHOOSEFOLDER) 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 else
{
gchar *filename = gtk_file_chooser_get_filename (fs);
gtkutil_check_file (gtk_file_chooser_get_filename (fs), freq); gtkutil_check_file (gtk_file_chooser_get_filename (fs), freq);
g_free (filename);
}
} }
/* this should call the "destroy" cb, where we free(freq) */ /* this should call the "destroy" cb, where we free(freq) */