From a56e545824e0cdce4bbfbdf9fc54aa7405194cd9 Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Thu, 21 Aug 2014 12:17:31 +0200
Subject: [PATCH] Fix crash when changing owner of file
Cherry picked commits from git master:
ab6aa9aca1c25c34e3f1aece63efbe05a2984397
bfa2d63249a1f5de986f7f1ad21d79920fa4947f
f7d1394a03e6d02cd5c67f9c85a142e33f14566f
https://bugzilla.redhat.com/show_bug.cgi?id=1090999
---
libnautilus-private/nautilus-file.c | 3 +-
src/nautilus-properties-window.c | 354 +++++++++++++++++-------------------
2 files changed, 164 insertions(+), 193 deletions(-)
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index 5e837f6..efef296 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -5670,7 +5670,8 @@ nautilus_file_get_owner_as_string (NautilusFile *file, gboolean include_real_nam
return NULL;
}
- if (file->details->uid == getuid ()) {
+ if (include_real_name &&
+ file->details->uid == getuid ()) {
/* Translators: "Me" is used to indicate the file is owned by me (the current user) */
user_name = g_strdup (_("Me"));
} else if (file->details->owner_real == NULL) {
diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c
index 6793b7a..7a81ddd 100644
--- a/src/nautilus-properties-window.c
+++ b/src/nautilus-properties-window.c
@@ -89,6 +89,22 @@
static GHashTable *windows;
static GHashTable *pending_lists;
+typedef struct {
+ NautilusFile *file;
+ char *owner;
+ GtkWindow *window;
+ unsigned int timeout;
+ gboolean cancelled;
+} OwnerChange;
+
+typedef struct {
+ NautilusFile *file;
+ char *group;
+ GtkWindow *window;
+ unsigned int timeout;
+ gboolean cancelled;
+} GroupChange;
+
struct NautilusPropertiesWindowDetails {
GList *original_files;
GList *target_files;
@@ -112,12 +128,8 @@ struct NautilusPropertiesWindowDetails {
guint update_directory_contents_timeout_id;
guint update_files_timeout_id;
- NautilusFile *group_change_file;
- char *group_change_group;
- unsigned int group_change_timeout;
- NautilusFile *owner_change_file;
- char *owner_change_owner;
- unsigned int owner_change_timeout;
+ GroupChange *group_change;
+ OwnerChange *owner_change;
GList *permission_buttons;
GList *permission_combos;
@@ -208,8 +220,8 @@ static void properties_window_update (NautilusPropertiesWindow *win
GList *files);
static void is_directory_ready_callback (NautilusFile *file,
gpointer data);
-static void cancel_group_change_callback (NautilusPropertiesWindow *window);
-static void cancel_owner_change_callback (NautilusPropertiesWindow *window);
+static void cancel_group_change_callback (GroupChange *change);
+static void cancel_owner_change_callback (OwnerChange *change);
static void parent_widget_destroyed_callback (GtkWidget *widget,
gpointer callback_data);
static void select_image_button_callback (GtkWidget *widget,
@@ -1363,78 +1375,70 @@ attach_ellipsizing_value_field (NautilusPropertiesWindow *window,
}
static void
+group_change_free (GroupChange *change)
+{
+ nautilus_file_unref (change->file);
+ g_free (change->group);
+ g_object_unref (change->window);
+
+ g_free (change);
+}
+
+static void
group_change_callback (NautilusFile *file,
GFile *res_loc,
GError *error,
- NautilusPropertiesWindow *window)
+ GroupChange *change)
{
- char *group;
-
- g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- g_assert (window->details->group_change_file == file);
+ NautilusPropertiesWindow *window;
- group = window->details->group_change_group;
- g_assert (group != NULL);
+ g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window));
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->group != NULL);
- /* Report the error if it's an error. */
- eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
- nautilus_report_error_setting_group (file, error, GTK_WINDOW (window));
+ if (!change->cancelled) {
+ /* Report the error if it's an error. */
+ eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, change);
+ nautilus_report_error_setting_group (change->file, error, change->window);
+ }
- nautilus_file_unref (file);
- g_free (group);
+ window = NAUTILUS_PROPERTIES_WINDOW(change->window);
+ if (window->details->group_change == change) {
+ window->details->group_change = NULL;
+ }
- window->details->group_change_file = NULL;
- window->details->group_change_group = NULL;
- g_object_unref (G_OBJECT (window));
+ group_change_free (change);
}
static void
-cancel_group_change_callback (NautilusPropertiesWindow *window)
+cancel_group_change_callback (GroupChange *change)
{
- NautilusFile *file;
- char *group;
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->group != NULL);
- file = window->details->group_change_file;
- g_assert (NAUTILUS_IS_FILE (file));
-
- group = window->details->group_change_group;
- g_assert (group != NULL);
-
- nautilus_file_cancel (file, (NautilusFileOperationCallback) group_change_callback, window);
-
- g_free (group);
- nautilus_file_unref (file);
-
- window->details->group_change_file = NULL;
- window->details->group_change_group = NULL;
- g_object_unref (window);
+ change->cancelled = TRUE;
+ nautilus_file_cancel (change->file, (NautilusFileOperationCallback) group_change_callback, change);
}
static gboolean
-schedule_group_change_timeout (NautilusPropertiesWindow *window)
+schedule_group_change_timeout (GroupChange *change)
{
- NautilusFile *file;
- char *group;
+ g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window));
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->group != NULL);
- g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
-
- file = window->details->group_change_file;
- g_assert (NAUTILUS_IS_FILE (file));
-
- group = window->details->group_change_group;
- g_assert (group != NULL);
+ change->timeout = 0;
eel_timed_wait_start
((EelCancelCallback) cancel_group_change_callback,
- window,
+ change,
_("Cancel Group Change?"),
- GTK_WINDOW (window));
+ change->window);
nautilus_file_set_group
- (file, group,
- (NautilusFileOperationCallback) group_change_callback, window);
+ (change->file, change->group,
+ (NautilusFileOperationCallback) group_change_callback, change);
- window->details->group_change_timeout = 0;
return FALSE;
}
@@ -1443,55 +1447,45 @@ schedule_group_change (NautilusPropertiesWindow *window,
NautilusFile *file,
const char *group)
{
+ GroupChange *change;
+
g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- g_assert (window->details->group_change_group == NULL);
- g_assert (window->details->group_change_file == NULL);
+ g_assert (window->details->group_change == NULL);
g_assert (NAUTILUS_IS_FILE (file));
- window->details->group_change_file = nautilus_file_ref (file);
- window->details->group_change_group = g_strdup (group);
- g_object_ref (G_OBJECT (window));
- window->details->group_change_timeout =
+ change = g_new0 (GroupChange, 1);
+
+ change->file = nautilus_file_ref (file);
+ change->group = g_strdup (group);
+ change->window = g_object_ref (G_OBJECT (window));
+ change->timeout =
g_timeout_add (CHOWN_CHGRP_TIMEOUT,
(GSourceFunc) schedule_group_change_timeout,
- window);
+ change);
+
+ window->details->group_change = change;
}
static void
unschedule_or_cancel_group_change (NautilusPropertiesWindow *window)
{
- NautilusFile *file;
- char *group;
+ GroupChange *change;
g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- file = window->details->group_change_file;
- group = window->details->group_change_group;
-
- g_assert ((file == NULL && group == NULL) ||
- (file != NULL && group != NULL));
+ change = window->details->group_change;
- if (file != NULL) {
- g_assert (NAUTILUS_IS_FILE (file));
-
- if (window->details->group_change_timeout == 0) {
- nautilus_file_cancel (file,
- (NautilusFileOperationCallback) group_change_callback, window);
- eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
+ if (change != NULL) {
+ if (change->timeout == 0) {
+ /* The operation was started, cancel it and let the operation callback free the change */
+ cancel_group_change_callback (change);
+ eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, change);
+ } else {
+ g_source_remove (change->timeout);
+ group_change_free (change);
}
- nautilus_file_unref (file);
- g_free (group);
-
- window->details->group_change_file = NULL;
- window->details->group_change_group = NULL;
- g_object_unref (G_OBJECT (window));
- }
-
- if (window->details->group_change_timeout > 0) {
- g_assert (file != NULL);
- g_source_remove (window->details->group_change_timeout);
- window->details->group_change_timeout = 0;
+ window->details->group_change = NULL;
}
}
@@ -1713,18 +1707,18 @@ combo_box_row_separator_func (GtkTreeModel *model,
static GtkComboBox *
attach_combo_box (GtkGrid *grid,
GtkWidget *sibling,
- gboolean two_columns)
+ gboolean three_columns)
{
GtkWidget *combo_box;
GtkWidget *aligner;
- if (!two_columns) {
+ if (!three_columns) {
combo_box = gtk_combo_box_text_new ();
} else {
GtkTreeModel *model;
GtkCellRenderer *renderer;
- model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+ model = GTK_TREE_MODEL (gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
combo_box = gtk_combo_box_new_with_model (model);
g_object_unref (G_OBJECT (model));
@@ -1778,78 +1772,70 @@ attach_group_combo_box (GtkGrid *grid,
}
static void
+owner_change_free (OwnerChange *change)
+{
+ nautilus_file_unref (change->file);
+ g_free (change->owner);
+ g_object_unref (change->window);
+
+ g_free (change);
+}
+
+static void
owner_change_callback (NautilusFile *file,
GFile *result_location,
GError *error,
- NautilusPropertiesWindow *window)
+ OwnerChange *change)
{
- char *owner;
-
- g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- g_assert (window->details->owner_change_file == file);
+ NautilusPropertiesWindow *window;
- owner = window->details->owner_change_owner;
- g_assert (owner != NULL);
+ g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window));
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->owner != NULL);
- /* Report the error if it's an error. */
- eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
- nautilus_report_error_setting_owner (file, error, GTK_WINDOW (window));
+ if (!change->cancelled) {
+ /* Report the error if it's an error. */
+ eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, change);
+ nautilus_report_error_setting_owner (file, error, change->window);
+ }
- nautilus_file_unref (file);
- g_free (owner);
+ window = NAUTILUS_PROPERTIES_WINDOW(change->window);
+ if (window->details->owner_change == change) {
+ window->details->owner_change = NULL;
+ }
- window->details->owner_change_file = NULL;
- window->details->owner_change_owner = NULL;
- g_object_unref (G_OBJECT (window));
+ owner_change_free (change);
}
static void
-cancel_owner_change_callback (NautilusPropertiesWindow *window)
+cancel_owner_change_callback (OwnerChange *change)
{
- NautilusFile *file;
- char *owner;
-
- file = window->details->owner_change_file;
- g_assert (NAUTILUS_IS_FILE (file));
-
- owner = window->details->owner_change_owner;
- g_assert (owner != NULL);
-
- nautilus_file_cancel (file, (NautilusFileOperationCallback) owner_change_callback, window);
-
- nautilus_file_unref (file);
- g_free (owner);
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->owner != NULL);
- window->details->owner_change_file = NULL;
- window->details->owner_change_owner = NULL;
- g_object_unref (window);
+ change->cancelled = TRUE;
+ nautilus_file_cancel (change->file, (NautilusFileOperationCallback) owner_change_callback, change);
}
static gboolean
-schedule_owner_change_timeout (NautilusPropertiesWindow *window)
+schedule_owner_change_timeout (OwnerChange *change)
{
- NautilusFile *file;
- char *owner;
-
- g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
-
- file = window->details->owner_change_file;
- g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window));
+ g_assert (NAUTILUS_IS_FILE (change->file));
+ g_assert (change->owner != NULL);
- owner = window->details->owner_change_owner;
- g_assert (owner != NULL);
+ change->timeout = 0;
eel_timed_wait_start
((EelCancelCallback) cancel_owner_change_callback,
- window,
+ change,
_("Cancel Owner Change?"),
- GTK_WINDOW (window));
+ change->window);
nautilus_file_set_owner
- (file, owner,
- (NautilusFileOperationCallback) owner_change_callback, window);
+ (change->file, change->owner,
+ (NautilusFileOperationCallback) owner_change_callback, change);
- window->details->owner_change_timeout = 0;
return FALSE;
}
@@ -1858,55 +1844,47 @@ schedule_owner_change (NautilusPropertiesWindow *window,
NautilusFile *file,
const char *owner)
{
+ OwnerChange *change;
+
g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- g_assert (window->details->owner_change_owner == NULL);
- g_assert (window->details->owner_change_file == NULL);
+ g_assert (window->details->owner_change == NULL);
g_assert (NAUTILUS_IS_FILE (file));
- window->details->owner_change_file = nautilus_file_ref (file);
- window->details->owner_change_owner = g_strdup (owner);
- g_object_ref (G_OBJECT (window));
- window->details->owner_change_timeout =
+ change = g_new0 (OwnerChange, 1);
+
+ change->file = nautilus_file_ref (file);
+ change->owner = g_strdup (owner);
+ change->window = g_object_ref (G_OBJECT (window));
+ change->timeout =
g_timeout_add (CHOWN_CHGRP_TIMEOUT,
(GSourceFunc) schedule_owner_change_timeout,
- window);
+ change);
+
+ window->details->owner_change = change;
}
static void
unschedule_or_cancel_owner_change (NautilusPropertiesWindow *window)
{
- NautilusFile *file;
- char *owner;
+ OwnerChange *change;
g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window));
- file = window->details->owner_change_file;
- owner = window->details->owner_change_owner;
+ change = window->details->owner_change;
- g_assert ((file == NULL && owner == NULL) ||
- (file != NULL && owner != NULL));
+ if (change != NULL) {
+ g_assert (NAUTILUS_IS_FILE (change->file));
- if (file != NULL) {
- g_assert (NAUTILUS_IS_FILE (file));
-
- if (window->details->owner_change_timeout == 0) {
- nautilus_file_cancel (file,
- (NautilusFileOperationCallback) owner_change_callback, window);
- eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
+ if (change->timeout == 0) {
+ /* The operation was started, cancel it and let the operation callback free the change */
+ cancel_owner_change_callback (change);
+ eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, change);
+ } else {
+ g_source_remove (change->timeout);
+ owner_change_free (change);
}
- nautilus_file_unref (file);
- g_free (owner);
-
- window->details->owner_change_file = NULL;
- window->details->owner_change_owner = NULL;
- g_object_unref (G_OBJECT (window));
- }
-
- if (window->details->owner_change_timeout > 0) {
- g_assert (file != NULL);
- g_source_remove (window->details->owner_change_timeout);
- window->details->owner_change_timeout = 0;
+ window->details->owner_change = NULL;
}
}
@@ -1914,20 +1892,15 @@ static void
changed_owner_callback (GtkComboBox *combo_box, NautilusFile* file)
{
NautilusPropertiesWindow *window;
- char *owner_text;
- char **name_array;
char *new_owner;
char *cur_owner;
g_assert (GTK_IS_COMBO_BOX (combo_box));
g_assert (NAUTILUS_IS_FILE (file));
- owner_text = combo_box_get_active_entry (combo_box, 0);
- if (! owner_text)
+ new_owner = combo_box_get_active_entry (combo_box, 2);
+ if (! new_owner)
return;
- name_array = g_strsplit (owner_text, " - ", 2);
- new_owner = name_array[0];
- g_free (owner_text);
cur_owner = nautilus_file_get_owner_name (file);
if (strcmp (new_owner, cur_owner) != 0) {
@@ -1937,7 +1910,7 @@ changed_owner_callback (GtkComboBox *combo_box, NautilusFile* file)
unschedule_or_cancel_owner_change (window);
schedule_owner_change (window, file, new_owner);
}
- g_strfreev (name_array);
+ g_free (new_owner);
g_free (cur_owner);
}
@@ -1951,6 +1924,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file)
GtkTreeIter iter;
char *user_name;
char *owner_name;
+ char *nice_owner_name;
int user_index;
int owner_index;
char **name_array;
@@ -1980,7 +1954,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file)
user_name = (char *)node->data;
name_array = g_strsplit (user_name, "\n", 2);
- if (name_array[1] != NULL) {
+ if (name_array[1] != NULL && *name_array[1] != 0) {
combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]);
} else {
combo_text = g_strdup (name_array[0]);
@@ -1990,6 +1964,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file)
gtk_list_store_set (store, &iter,
0, combo_text,
1, user_name,
+ 2, name_array[0],
-1);
g_strfreev (name_array);
@@ -1997,8 +1972,9 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file)
}
}
- owner_name = nautilus_file_get_string_attribute (file, "owner");
- owner_index = tree_model_get_entry_index (model, 0, owner_name);
+ owner_name = nautilus_file_get_owner_name (file);
+ owner_index = tree_model_get_entry_index (model, 2, owner_name);
+ nice_owner_name = nautilus_file_get_string_attribute (file, "owner");
/* If owner wasn't in list, we prepend it (with a separator).
* This can happen if the owner is an id with no matching
@@ -2011,30 +1987,24 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file)
gtk_list_store_set (store, &iter,
0, "-",
1, NULL,
+ 2, NULL,
-1);
}
- name_array = g_strsplit (owner_name, " - ", 2);
- if (name_array[1] != NULL) {
- user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]);
- } else {
- user_name = g_strdup (name_array[0]);
- }
owner_index = 0;
gtk_list_store_prepend (store, &iter);
gtk_list_store_set (store, &iter,
- 0, owner_name,
- 1, user_name,
+ 0, nice_owner_name,
+ 1, owner_name,
+ 2, owner_name,
-1);
-
- g_free (user_name);
- g_strfreev (name_array);
}
gtk_combo_box_set_active (combo_box, owner_index);
g_free (owner_name);
+ g_free (nice_owner_name);
g_list_free_full (users, g_free);
}
--
2.0.4