Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 146283 Details for
Bug 223961
Permissions changes crash with selinux disabled
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
New fixed version of selinux patch
nautilus-2.16.2-selinux2.patch (text/plain), 47.52 KB, created by
Alexander Larsson
on 2007-01-23 11:11:55 UTC
(
hide
)
Description:
New fixed version of selinux patch
Filename:
MIME Type:
Creator:
Alexander Larsson
Created:
2007-01-23 11:11:55 UTC
Size:
47.52 KB
patch
obsolete
>--- nautilus-2.17.90/libnautilus-private/nautilus-file.c.selinux 2007-01-22 10:10:45.000000000 +0100 >+++ nautilus-2.17.90/libnautilus-private/nautilus-file.c 2007-01-23 10:04:29.000000000 +0100 >@@ -3569,7 +3569,7 @@ > * context > * @file: NautilusFile representing the file in question. > * >- * Returns: Newly allocated string ready to display to the user. >+ * Returns: Newly allocated string ready to display to the user, or NULL. > * > **/ > char * >@@ -3602,6 +3602,134 @@ > return translated; > } > >+/** >+ * nautilus_file_get_selinux_matchpathcon: >+ * >+ * Get a user-displayable string representing a file's default selinux >+ * context (as from matchpathcon). Only works on local files. >+ * @file: NautilusFile representing the file in question. >+ * >+ * Returns: Newly allocated string ready to display to the user, or NULL. >+ * >+ **/ >+char * >+nautilus_file_get_selinux_matchpathcon (NautilusFile *file) >+{ >+ char *translated; >+ char *raw; >+ char *uri; >+ char *fname; >+ >+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); >+ >+ translated = NULL; >+#ifdef HAVE_SELINUX >+ uri = nautilus_file_get_uri (file); >+ fname = gnome_vfs_get_local_path_from_uri (uri); >+ >+ if (!fname) { >+ return NULL; >+ } >+ >+ raw = NULL; >+ if (matchpathcon (fname, file->details->info->permissions, &raw) == 0) { >+ if (selinux_raw_to_trans_context (raw, &translated) == 0) { >+ char *tmp; >+ tmp = g_strdup (translated); >+ freecon (translated); >+ translated = tmp; >+ } >+ freecon (raw); >+ } >+ >+ g_free (fname); >+ g_free (uri); >+#endif >+ >+ return translated; >+} >+ >+static void >+set_selinux_context_callback (GnomeVFSAsyncHandle *handle, >+ GnomeVFSResult result, >+ GnomeVFSFileInfo *new_info, >+ gpointer callback_data) >+{ >+ set_permissions_callback (handle, result, new_info, callback_data); >+} >+ >+void >+nautilus_file_set_selinux_context (NautilusFile *file, >+ const char *selinux_context, >+ NautilusFileOperationCallback callback, >+ gpointer callback_data) >+{ >+ Operation *op; >+ GnomeVFSURI *vfs_uri; >+ GnomeVFSFileInfo *partial_file_info; >+ GnomeVFSFileInfoOptions options; >+ char *rcontext; >+ >+ rcontext = NULL; >+ >+ /* this is probably mostly right... */ >+ if (!nautilus_file_can_set_permissions (file)) { >+ /* Claim that something changed even if the permission change failed. >+ * This makes it easier for some clients who see the "reverting" >+ * to the old permissions as "changing back". >+ */ >+ nautilus_file_changed (file); >+ (* callback) (file, GNOME_VFS_ERROR_ACCESS_DENIED, callback_data); >+ return; >+ } >+ >+ /* Test the permissions-haven't-changed case explicitly >+ * because we don't want to send the file-changed signal if >+ * nothing changed. >+ */ >+ if (file->details->info->selinux_context != NULL && >+ strcmp(selinux_context, file->details->info->selinux_context) == 0) { >+ (* callback) (file, GNOME_VFS_OK, callback_data); >+ return; >+ } >+ >+#ifdef HAVE_SELINUX >+ /* this is really const, but prototype is wrong, *sigh* */ >+ if (selinux_trans_to_raw_context((char *)selinux_context, &rcontext)) { >+ (* callback) (file, GNOME_VFS_ERROR_NO_MEMORY, callback_data); >+ return; >+ } >+ selinux_context = rcontext; >+#endif >+ >+ /* Set up a context change operation. */ >+ op = operation_new (file, callback, callback_data); >+ op->use_slow_mime = file->details->got_slow_mime_type; >+ >+ options = NAUTILUS_FILE_DEFAULT_FILE_INFO_OPTIONS; >+ if (op->use_slow_mime) { >+ options |= GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE; >+ } >+ /* Change the file-on-disk context. */ >+ partial_file_info = gnome_vfs_file_info_new (); >+ g_free (partial_file_info->selinux_context); >+ partial_file_info->selinux_context = g_strdup (selinux_context); >+ vfs_uri = nautilus_file_get_gnome_vfs_uri (file); >+ gnome_vfs_async_set_file_info (&op->handle, >+ vfs_uri, partial_file_info, >+ GNOME_VFS_SET_FILE_INFO_SELINUX_CONTEXT, >+ options, >+ GNOME_VFS_PRIORITY_DEFAULT, >+ set_selinux_context_callback, op); >+ gnome_vfs_file_info_unref (partial_file_info); >+ gnome_vfs_uri_unref (vfs_uri); >+ >+#ifdef HAVE_SELINUX >+ freecon (rcontext); >+#endif >+} >+ >+ > static char * > get_real_name (const char *name, const char *gecos) > { >@@ -3804,7 +3932,7 @@ > GnomeVFSResult result, > GnomeVFSFileInfo *new_info, > gpointer callback_data) >-{ >+{ /* FIXME: this is identical to set_permissions_callback */ > Operation *op; > > op = callback_data; >--- nautilus-2.17.90/libnautilus-private/nautilus-file.h.selinux 2007-01-11 10:58:31.000000000 +0100 >+++ nautilus-2.17.90/libnautilus-private/nautilus-file.h 2007-01-23 09:15:44.000000000 +0100 >@@ -200,6 +200,7 @@ > GList * nautilus_file_get_settable_group_names (NautilusFile *file); > gboolean nautilus_file_can_get_selinux_context (NautilusFile *file); > char * nautilus_file_get_selinux_context (NautilusFile *file); >+char * nautilus_file_get_selinux_matchpathcon (NautilusFile *file); > > /* "Capabilities". */ > gboolean nautilus_file_can_read (NautilusFile *file); >@@ -226,6 +227,10 @@ > GnomeVFSFilePermissions permissions, > NautilusFileOperationCallback callback, > gpointer callback_data); >+void nautilus_file_set_selinux_context (NautilusFile *file, >+ const char *selinux_context, >+ NautilusFileOperationCallback callback, >+ gpointer callback_data); > void nautilus_file_rename (NautilusFile *file, > const char *new_name, > NautilusFileOperationCallback callback, >--- nautilus-2.17.90/libnautilus-private/nautilus-file-operations.c.selinux 2007-01-11 12:36:02.000000000 +0100 >+++ nautilus-2.17.90/libnautilus-private/nautilus-file-operations.c 2007-01-23 09:15:44.000000000 +0100 >@@ -63,6 +63,10 @@ > #include "nautilus-trash-monitor.h" > #include "nautilus-file-utilities.h" > >+#ifdef HAVE_SELINUX >+#include <selinux/selinux.h> >+#endif >+ > typedef enum TransferKind TransferKind; > typedef struct TransferInfo TransferInfo; > typedef struct IconPositionIterator IconPositionIterator; >@@ -2953,6 +2957,7 @@ > GnomeVFSFilePermissions file_mask; > GnomeVFSFilePermissions dir_permissions; > GnomeVFSFilePermissions dir_mask; >+ char *context; > NautilusSetPermissionsCallback callback; > gpointer callback_data; > }; >@@ -2980,6 +2985,8 @@ > GnomeVFSURI *uri; > char *uri_str; > struct FileInfo *file_info; >+ int flags; >+ int options; > > info = callback_data; > >@@ -3010,10 +3017,18 @@ > vfs_info->permissions = > (file_info->permissions & ~info->file_mask) | > info->file_permissions; >+ flags = GNOME_VFS_SET_FILE_INFO_PERMISSIONS; >+ options = GNOME_VFS_FILE_INFO_DEFAULT; >+ if (info->context) { >+ flags |= GNOME_VFS_SET_FILE_INFO_SELINUX_CONTEXT; >+ vfs_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SELINUX_CONTEXT; >+ options |= GNOME_VFS_FILE_INFO_GET_SELINUX_CONTEXT; >+ g_free (vfs_info->selinux_context); >+ vfs_info->selinux_context = g_strdup (info->context); >+ } > > gnome_vfs_async_set_file_info (&info->handle, uri, vfs_info, >- GNOME_VFS_SET_FILE_INFO_PERMISSIONS, >- GNOME_VFS_FILE_INFO_DEFAULT, >+ flags, options, > GNOME_VFS_PRIORITY_DEFAULT, > set_permissions_set_file_info, > info); >@@ -3021,7 +3036,6 @@ > gnome_vfs_file_info_unref (vfs_info); > g_free (file_info->name); > g_free (file_info); >- > } > > static void >@@ -3066,13 +3080,11 @@ > } > } > >- > if (result != GNOME_VFS_OK) { > /* Finished with this dir, work on the files */ > info->current_file = NULL; > set_permissions_set_file_info (NULL, GNOME_VFS_OK, NULL, info); > } >- > } > > /* Also called for the toplevel dir */ >@@ -3084,7 +3096,8 @@ > { > struct RecursivePermissionsInfo *info; > char *uri_str; >- >+ int options; >+ > info = callback_data; > > if (result == GNOME_VFS_OK && handle != NULL) { >@@ -3093,9 +3106,13 @@ > g_free (uri_str); > } > >+ options = GNOME_VFS_FILE_INFO_DEFAULT; >+ if (info->context) { >+ options |= GNOME_VFS_FILE_INFO_GET_SELINUX_CONTEXT; >+ } > gnome_vfs_async_load_directory_uri (&info->handle, > info->current_dir, >- GNOME_VFS_FILE_INFO_DEFAULT, >+ options, > 50, > GNOME_VFS_PRIORITY_DEFAULT, > set_permissions_got_files, >@@ -3107,6 +3124,8 @@ > { > struct DirInfo *dir_info; > GnomeVFSFileInfo *vfs_info; >+ int flags; >+ int options; > > gnome_vfs_uri_unref (info->current_dir); > >@@ -3114,6 +3133,7 @@ > /* No more directories, finished! */ > info->callback (info->callback_data); > /* All parts of info should be freed now */ >+ g_free (info->context); > g_free (info); > return; > } >@@ -3128,12 +3148,18 @@ > vfs_info->permissions = > (dir_info->permissions & ~info->dir_mask) | > info->dir_permissions; >- >- gnome_vfs_async_set_file_info (&info->handle, >- info->current_dir, >- vfs_info, >- GNOME_VFS_SET_FILE_INFO_PERMISSIONS, >- GNOME_VFS_FILE_INFO_DEFAULT, >+ flags = GNOME_VFS_SET_FILE_INFO_PERMISSIONS; >+ options = GNOME_VFS_FILE_INFO_DEFAULT; >+ if (info->context) { >+ flags |= GNOME_VFS_SET_FILE_INFO_SELINUX_CONTEXT; >+ vfs_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SELINUX_CONTEXT; >+ options |= GNOME_VFS_FILE_INFO_GET_SELINUX_CONTEXT; >+ g_free (vfs_info->selinux_context); >+ vfs_info->selinux_context = g_strdup (info->context); >+ } >+ >+ gnome_vfs_async_set_file_info (&info->handle, info->current_dir, >+ vfs_info, flags, options, > GNOME_VFS_PRIORITY_DEFAULT, > set_permissions_load_dir, > info); >@@ -3148,6 +3174,7 @@ > GnomeVFSFilePermissions file_mask, > GnomeVFSFilePermissions dir_permissions, > GnomeVFSFilePermissions dir_mask, >+ const char *context, > NautilusSetPermissionsCallback callback, > gpointer callback_data) > { >@@ -3161,6 +3188,22 @@ > info->file_mask = file_mask; > info->dir_permissions = dir_permissions; > info->dir_mask = dir_mask; >+ if (context) { >+ char *rcontext; >+ >+ rcontext = info->context = NULL; >+#ifdef HAVE_SELINUX >+ /* this is really const, but prototype is wrong, *sigh* */ >+ if (selinux_trans_to_raw_context((char *)context, &rcontext)) { >+ g_error ("selinux_trans_to_raw_context: failed to allocate bytes"); >+ return; >+ } >+ info->context = g_strdup (rcontext); >+ freecon (rcontext); >+#endif >+ } else { >+ info->context = NULL; >+ } > info->callback = callback; > info->callback_data = callback_data; > >@@ -3168,6 +3211,8 @@ > > if (info->current_dir == NULL) { > info->callback (info->callback_data); >+ /* All parts of info should be freed now */ >+ g_free (info->context); > g_free (info); > return; > } >--- nautilus-2.17.90/libnautilus-private/nautilus-file-operations.h.selinux 2007-01-03 09:52:25.000000000 +0100 >+++ nautilus-2.17.90/libnautilus-private/nautilus-file-operations.h 2007-01-23 09:15:44.000000000 +0100 >@@ -76,6 +76,7 @@ > GnomeVFSFilePermissions file_mask, > GnomeVFSFilePermissions folder_permissions, > GnomeVFSFilePermissions folder_mask, >+ const char *context, > NautilusSetPermissionsCallback callback, > gpointer callback_data); > >--- nautilus-2.17.90/src/file-manager/fm-error-reporting.c.selinux 2007-01-03 09:52:12.000000000 +0100 >+++ nautilus-2.17.90/src/file-manager/fm-error-reporting.c 2007-01-23 09:15:44.000000000 +0100 >@@ -252,6 +252,38 @@ > g_free (message); > } > >+void >+fm_report_error_setting_selinux (NautilusFile *file, >+ GnomeVFSResult error, >+ GtkWindow *parent_window) >+{ >+ char *file_name; >+ char *message; >+ >+ if (error == GNOME_VFS_OK) { >+ return; >+ } >+ >+ file_name = nautilus_file_get_display_name (file); >+ >+ switch (error) { >+ case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM: >+ message = g_strdup_printf (_("Couldn't change the SELinux security context of \"%s\" because it is on a read-only disk"), >+ file_name); >+ break; >+ default: >+ /* We should invent decent error messages for every case we actually experience. */ >+ g_warning ("Hit unhandled case %d (%s) in fm_report_error_setting_permissions", >+ error, gnome_vfs_result_to_string (error)); >+ message = g_strdup_printf (_("Sorry, couldn't change the permissions of \"%s\"."), file_name); >+ } >+ >+ eel_show_error_dialog (_("The SELinux security context could not be changed."), message, parent_window); >+ >+ g_free (file_name); >+ g_free (message); >+} >+ > typedef struct _FMRenameData { > char *name; > NautilusFileOperationCallback callback; >--- nautilus-2.17.90/src/file-manager/fm-error-reporting.h.selinux 2007-01-03 09:52:12.000000000 +0100 >+++ nautilus-2.17.90/src/file-manager/fm-error-reporting.h 2007-01-23 09:15:44.000000000 +0100 >@@ -39,7 +39,10 @@ > GnomeVFSResult error_code, > GtkWindow *parent_window); > void fm_report_error_setting_permissions (NautilusFile *file, >- GnomeVFSResult error_code, >+ GnomeVFSResult error_code, >+ GtkWindow *parent_window); >+void fm_report_error_setting_selinux (NautilusFile *file, >+ GnomeVFSResult error_code, > GtkWindow *parent_window); > void fm_report_error_setting_owner (NautilusFile *file, > GnomeVFSResult error_code, >--- nautilus-2.17.90/src/file-manager/fm-properties-window.c.selinux 2007-01-11 11:53:01.000000000 +0100 >+++ nautilus-2.17.90/src/file-manager/fm-properties-window.c 2007-01-23 09:15:44.000000000 +0100 >@@ -83,6 +83,10 @@ > #include <libnautilus-private/nautilus-undo.h> > #include <string.h> > >+#ifdef HAVE_SELINUX >+# include <selinux/selinux.h> >+#endif >+ > #define PREVIEW_IMAGE_WIDTH 96 > > #define ROW_PAD 6 >@@ -102,7 +106,7 @@ > > GtkWidget *icon_button; > GtkWidget *icon_image; >- GtkWidget *icon_chooser; >+ GtkWidget *icon_chooser; > > GtkWidget *name_label; > GtkWidget *name_field; >@@ -124,12 +128,15 @@ > unsigned int owner_change_timeout; > > GList *permission_buttons; >- GList *permission_combos; >+ GList *permission_combos; /* how is this deallocated???? */ >+ GList *selinux_combo; > GHashTable *initial_permissions; > gboolean has_recursive_apply; > > GList *value_fields; > >+ GList *edit_fields; >+ > GList *mime_list; > > gboolean deep_count_finished; >@@ -208,6 +215,10 @@ > GtkComboBox *combo); > static void value_field_update (FMPropertiesWindow *window, > GtkLabel *field); >+static void edit_field_update (FMPropertiesWindow *window, >+ GtkEntry *field); >+static void popup_field_update (FMPropertiesWindow *window, >+ GtkComboBox *entry); > static void properties_window_update (FMPropertiesWindow *window, > GList *files); > static void is_directory_ready_callback (NautilusFile *file, >@@ -235,10 +246,32 @@ > int row, > int column, > const char *initial_text); >+static void attach_selinux_data_edit_field (GtkEntry *entry, >+ char *attr_value, >+ char *def_attr_value); >+static void attach_selinux_data_popup_field (GtkComboBox *comb, >+ char *attr_val, >+ char *def_attr_val); >+ > > G_DEFINE_TYPE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_WINDOW); > #define parent_class fm_properties_window_parent_class > >+static void >+maybe_gtk_entry_set_text (GtkEntry *entry, const char *val) >+{ >+ char *old_val; >+ >+ g_assert (GTK_IS_ENTRY (entry)); >+ >+ old_val = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); >+ >+ if (strcmp (old_val, val) != 0) { >+ gtk_entry_set_text (entry, val); >+ } >+ g_free(old_val); >+} >+ > static gboolean > is_multi_file_window (FMPropertiesWindow *window) > { >@@ -259,6 +292,39 @@ > return FALSE; > } > >+static gboolean >+multi_have_same_selinux_context (FMPropertiesWindow *window) >+{ >+ GList *l; >+ char *cntx; >+ >+ cntx = NULL; >+ for (l = window->details->original_files; l != NULL; l = l->next) { >+ NautilusFile *file; >+ >+ file = NAUTILUS_FILE (l->data); >+ if (!nautilus_file_is_gone (file)) { >+ char *tmp; >+ >+ tmp = nautilus_file_get_string_attribute_with_default (file, "selinux_context"); >+ if (!cntx) { >+ cntx = tmp; >+ } else if (strcmp (cntx, tmp)) { >+ g_free (tmp); >+ g_free (cntx); >+ return FALSE; >+ } >+ else { >+ g_free (tmp); >+ } >+ } >+ } >+ >+ g_free (cntx); >+ >+ return TRUE; >+} >+ > static int > get_not_gone_original_file_count (FMPropertiesWindow *window) > { >@@ -496,7 +562,7 @@ > return; > } > >- uris = g_strsplit (selection_data->data, "\r\n", 0); >+ uris = g_strsplit ((char *) selection_data->data, "\r\n", 0); > exactly_one = uris[0] != NULL && (uris[1] == NULL || uris[1][0] == '\0'); > > >@@ -577,7 +643,7 @@ > > static void > set_name_field (FMPropertiesWindow *window, const gchar *original_name, >- const gchar *name) >+ const gchar *name) > { > gboolean new_widget; > gboolean use_label; >@@ -643,11 +709,7 @@ > * currently showing. This causes minimal ripples (e.g. > * selection change). > */ >- gchar *displayed_name = gtk_editable_get_chars (GTK_EDITABLE (window->details->name_field), 0, -1); >- if (strcmp (displayed_name, name) != 0) { >- gtk_entry_set_text (GTK_ENTRY (window->details->name_field), name); >- } >- g_free (displayed_name); >+ maybe_gtk_entry_set_text (GTK_ENTRY (window->details->name_field), name); > } > } > } >@@ -723,7 +785,6 @@ > name_field_restore_original_name (NautilusEntry *name_field) > { > const char *original_name; >- char *displayed_name; > > original_name = (const char *) g_object_get_data (G_OBJECT (name_field), > "original_name"); >@@ -732,14 +793,8 @@ > return; > } > >- displayed_name = gtk_editable_get_chars (GTK_EDITABLE (name_field), 0, -1); >- >- if (strcmp (original_name, displayed_name) != 0) { >- gtk_entry_set_text (GTK_ENTRY (name_field), original_name); >- } >+ maybe_gtk_entry_set_text (GTK_ENTRY (name_field), original_name); > nautilus_entry_select_all (name_field); >- >- g_free (displayed_name); > } > > static void >@@ -852,7 +907,7 @@ > word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp); > eel_g_list_free_deep (keywords); > >- return (word != NULL); >+ return word != NULL; > } > > static void >@@ -1119,7 +1174,7 @@ > b = b->next; > } > >- return (a == b); >+ return a == b; > } > > static GList * >@@ -1201,6 +1256,14 @@ > for (l = window->details->value_fields; l != NULL; l = l->next) { > value_field_update (window, GTK_LABEL (l->data)); > } >+ >+ for (l = window->details->edit_fields; l != NULL; l = l->next) { >+ edit_field_update (window, GTK_ENTRY (l->data)); >+ } >+ >+ for (l = window->details->selinux_combo; l != NULL; l = l->next) { >+ popup_field_update (window, GTK_COMBO_BOX (l->data)); >+ } > } > > mime_list = get_mime_list (window); >@@ -1381,6 +1444,111 @@ > ellipsize_text); > } > >+static void >+edit_field_update_internal (GtkEntry *entry, >+ GList *file_list) >+{ >+ const char *attr_name; >+ char *attr_value; >+ char *def_attr_value; >+ char *inconsistent_string; >+ >+ g_assert (GTK_IS_ENTRY (entry)); >+ >+ attr_name = g_object_get_data (G_OBJECT (entry), "file_attribute"); >+ inconsistent_string = g_object_get_data (G_OBJECT (entry), >+ "inconsistent_string"); >+ def_attr_value = g_object_get_data (G_OBJECT (entry), >+ "matchpathcon_cntx"); >+ >+ attr_value = file_list_get_string_attribute (file_list, attr_name, >+ inconsistent_string); >+ >+ maybe_gtk_entry_set_text (GTK_ENTRY (entry), attr_value); >+ >+ /* JFIXME: this isn't generic, *sigh* ... */ >+ attach_selinux_data_edit_field (entry, attr_value, def_attr_value); >+ g_free (attr_value); >+} >+ >+static void >+edit_field_update (FMPropertiesWindow *window, GtkEntry *entry) >+{ >+ gboolean use_original; >+ >+ if (gtk_widget_is_focus (GTK_WIDGET (entry))) { >+ return; >+ } >+ >+ use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "show_original")); >+ >+ edit_field_update_internal (entry, >+ (use_original ? >+ window->details->original_files : >+ window->details->target_files)); >+} >+ >+static void >+popup_field_update_internal (GtkComboBox *combo, >+ GList *file_list) >+{ >+ const char *attr_name; >+ char *attr_value; >+ char *def_attr_value; >+ char *inconsistent_string; >+ char *cntx_type; >+ GtkTreeIter iter; >+ >+ g_assert (GTK_IS_COMBO_BOX (combo)); >+ >+ if (gtk_widget_is_focus (GTK_WIDGET (combo))) { >+ return; >+ } >+ >+ attr_name = g_object_get_data (G_OBJECT (combo), "file_attribute"); >+ inconsistent_string = g_object_get_data (G_OBJECT (combo), >+ "inconsistent_string"); >+ def_attr_value = g_object_get_data (G_OBJECT (combo), >+ "matchpathcon_cntx"); >+ >+ attr_value = file_list_get_string_attribute (file_list, attr_name, >+ inconsistent_string); >+ >+ /* JFIXME: this isn't generic, *sigh* ... */ >+ >+ if (gtk_combo_box_get_active_iter (combo, &iter)) { >+ GtkTreeModel *model = gtk_combo_box_get_model (combo); >+ >+ /* don't update, if it's identical */ >+ gtk_tree_model_get (model, &iter, 0, &cntx_type, -1); >+ if (cntx_type && strcmp (cntx_type, attr_value) == 0) { >+ g_free (attr_value); >+ return; >+ } >+ } >+ >+ attach_selinux_data_popup_field (combo, attr_value, def_attr_value); >+ >+ g_free (attr_value); >+} >+ >+static void >+popup_field_update (FMPropertiesWindow *window, GtkComboBox *combo) >+{ >+ gboolean use_original; >+ >+ if (window->details->selinux_combo) { >+ return; /* FIXME: must be true: horrible UI, if working */ >+ } >+ >+ use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "show_original")); >+ >+ popup_field_update_internal (combo, >+ (use_original ? >+ window->details->original_files : >+ window->details->target_files)); >+} >+ > static GtkLabel * > attach_label (GtkTable *table, > int row, >@@ -1432,6 +1600,45 @@ > return attach_label (table, row, column, initial_text, FALSE, FALSE, FALSE, TRUE, FALSE); > } > >+static GtkEntry * >+attach_edit (GtkTable *table, >+ int row, >+ int column, >+ const char *initial_text, >+ gboolean right_aligned, >+ gboolean bold, >+ gboolean ellipsize_text, >+ gboolean selectable, >+ gboolean mnemonic) >+{ >+ GtkWidget *entry_field; >+ >+ entry_field = nautilus_entry_new (); >+ gtk_entry_set_text (GTK_ENTRY (entry_field), initial_text); >+ >+ gtk_entry_set_alignment (GTK_ENTRY (entry_field), right_aligned ? 1 : 0); >+ gtk_widget_show (entry_field); >+ gtk_table_attach (table, entry_field, >+ column, column + 1, >+ row, row + 1, >+ ellipsize_text >+ ? GTK_FILL | GTK_EXPAND >+ : GTK_FILL, >+ 0, >+ 0, 0); >+ >+ return GTK_ENTRY (entry_field); >+} >+ >+static GtkEntry * >+attach_edit_label (GtkTable *table, >+ int row, >+ int column, >+ const char *initial_text) >+{ >+ return attach_edit (table, row, column, initial_text, FALSE, FALSE, FALSE, TRUE, FALSE); >+} >+ > static GtkLabel * > attach_ellipsizing_value_label (GtkTable *table, > int row, >@@ -1491,6 +1698,672 @@ > FALSE); > } > >+static void >+start_long_operation (FMPropertiesWindow *window) >+{ >+ if (window->details->long_operation_underway == 0) { >+ /* start long operation */ >+ GdkCursor * cursor; >+ >+ cursor = gdk_cursor_new (GDK_WATCH); >+ gdk_window_set_cursor (GTK_WIDGET (window)->window, cursor); >+ gdk_cursor_unref (cursor); >+ } >+ window->details->long_operation_underway ++; >+} >+ >+static void >+end_long_operation (FMPropertiesWindow *window) >+{ >+ if (GTK_WIDGET (window)->window != NULL && >+ window->details->long_operation_underway == 1) { >+ /* finished !! */ >+ gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL); >+ } >+ window->details->long_operation_underway--; >+} >+ >+static void >+selinux_change_callback (NautilusFile *file, GnomeVFSResult result, gpointer callback_data) >+{ >+ FMPropertiesWindow *window; >+ g_assert (callback_data != NULL); >+ >+ window = FM_PROPERTIES_WINDOW (callback_data); >+ end_long_operation (window); >+ >+ /* Report the error if it's an error. */ >+ fm_report_error_setting_selinux (file, result, NULL); >+ >+ g_object_unref (window); >+} >+ >+static void >+selinux_done_editing (FMPropertiesWindow *window, char *selinux_context) >+{ >+ GList *l; >+ >+ /* Accept changes. */ >+ for (l = window->details->target_files; l != NULL; l = l->next) { >+ NautilusFile *file; >+ >+ file = NAUTILUS_FILE (l->data); >+ >+ start_long_operation (window); >+ g_object_ref (window); >+ nautilus_file_set_selinux_context (file, selinux_context, >+ selinux_change_callback, >+ window); >+ } >+} >+ >+static gboolean >+selinux_focus_out (NautilusEntry *entry, GdkEventFocus *event, gpointer cb_data) >+{ >+ g_assert (NAUTILUS_IS_ENTRY (entry)); >+ g_assert (FM_IS_PROPERTIES_WINDOW (cb_data)); >+ >+ if (GTK_WIDGET_SENSITIVE (entry)) { >+ char *tmp; >+ >+ tmp = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); >+ selinux_done_editing (FM_PROPERTIES_WINDOW (cb_data), tmp); >+ g_free (tmp); >+ } >+ >+ return FALSE; >+} >+ >+static void >+selinux_entry_activate (NautilusEntry *entry, gpointer cb_data) >+{ >+ char *tmp; >+ >+ g_assert (NAUTILUS_IS_ENTRY (entry)); >+ g_assert (FM_IS_PROPERTIES_WINDOW (cb_data)); >+ >+ tmp = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); >+ selinux_done_editing (FM_PROPERTIES_WINDOW (cb_data), tmp); >+ g_free (tmp); >+ >+ nautilus_entry_select_all_at_idle (entry); >+} >+ >+/* NOTE: This modifies cntx */ >+static void >+selinux_split_cntx (char *cntx, >+ const char **ret_attr_u, >+ const char **ret_attr_r, >+ const char **ret_attr_t, >+ const char **ret_attr_s) >+{ >+ const char *attr_u; >+ const char *attr_r; >+ const char *attr_t; >+ const char *attr_s; >+ >+ attr_u = cntx; >+ if (!(attr_r = strchr (attr_u, ':'))) { >+ attr_r = "object_r"; /* shouldn't happen */ >+ } else { >+ *((char *)attr_r++) = 0; >+ } >+ >+ if (!(attr_t = strchr (attr_r, ':'))) { >+ attr_t = "file_t"; /* shouldn't happen */ >+ } else { >+ *((char *)attr_t++) = 0; >+ } >+ >+ if ((attr_s = strchr (attr_t, ':'))) { >+ *((char *)attr_s++) = 0; >+ } >+ >+ *ret_attr_u = attr_u; >+ *ret_attr_r = attr_r; >+ *ret_attr_t = attr_t; >+ *ret_attr_s = attr_s; >+} >+ >+static void >+selinux_popup_activate (GtkComboBox *comb, gpointer cb_data) >+{ >+ char *cntx_type; >+ char *orig_type; >+ const char *attr_u; >+ const char *attr_r; >+ const char *attr_t; >+ const char *attr_s; >+ char *tmp; >+ GtkTreeIter iter; >+ >+ g_assert (GTK_IS_COMBO_BOX (comb)); >+ g_assert (FM_IS_PROPERTIES_WINDOW (cb_data)); >+ >+ if (!gtk_combo_box_get_active_iter (comb, &iter)) { >+ return; >+ } else { >+ >+ GtkTreeModel *model = gtk_combo_box_get_model (comb); >+ gtk_tree_model_get (model, &iter, 0, &cntx_type, -1); >+ } >+ >+ if (!(orig_type = g_object_get_data (G_OBJECT (comb), >+ "original_cntx"))) { >+ return; >+ } >+ orig_type = g_strdup (orig_type); >+ >+ selinux_split_cntx (orig_type, &attr_u, &attr_r, &attr_t, &attr_s); >+ tmp = g_strjoin (":", attr_u, attr_r, cntx_type, attr_s, NULL); >+ g_free (orig_type); >+ >+ selinux_done_editing (FM_PROPERTIES_WINDOW (cb_data), tmp); >+ g_free (tmp); >+} >+ >+static char * >+cust_type_next_line (GIOChannel *ioc_ctypes) >+{ >+ char *data; >+ gsize term; >+ GError *errc; >+ >+ data = NULL; >+ term = 0; >+ errc = NULL; >+ >+ if (G_IO_STATUS_NORMAL == g_io_channel_read_line (ioc_ctypes, &data, >+ NULL, &term, &errc)) { >+ data[term] = 0; >+ return data; >+ } >+ >+ return NULL; >+} >+ >+static GSList * >+selinux__type_list (void) >+{ >+ static GSList *cust_types; >+ static time_t file_mtime; >+ const char *fname_ctypes; >+ struct stat buf; >+ GIOChannel *ioc_ctypes; >+ GError *errc; >+ GSList *scan; >+ int fd; >+ >+#ifndef HAVE_SELINUX >+ if (cust_types) { >+ return cust_types; >+ } >+#else >+ fname_ctypes = selinux_customizable_types_path (); >+ if (cust_types && file_mtime && !stat (fname_ctypes, &buf) && >+ (file_mtime == buf.st_mtime)) { >+ return cust_types; >+ } >+#endif >+ >+ if (cust_types) { >+ for (scan = cust_types; scan; scan = scan->next) { >+ g_free (scan->data); >+ } >+ g_slist_free (cust_types); >+ cust_types = NULL; >+ } >+ >+ cust_types = g_slist_prepend (cust_types, g_strdup ("tmp_t")); >+ cust_types = g_slist_prepend (cust_types, g_strdup ("user_home_t")); >+ /* cust_types = g_slist_prepend (cust_types, g_strdup ("user_tmp_t")); */ >+ >+#ifdef HAVE_SELINUX >+ /* read types, one per line... */ >+ fname_ctypes = selinux_customizable_types_path (); >+ errc = NULL; >+ if ((ioc_ctypes = g_io_channel_new_file (fname_ctypes, "r", &errc))) { >+ char *data = NULL; >+ >+ while ((data = cust_type_next_line (ioc_ctypes))) { >+ cust_types = g_slist_prepend (cust_types, data); >+ } >+ >+ fd = g_io_channel_unix_get_fd (ioc_ctypes); >+ if (!fstat (fd, &buf)) { >+ file_mtime = buf.st_mtime; >+ } >+ >+ g_io_channel_unref (ioc_ctypes); >+ } >+#endif >+ >+ return cust_types; >+} >+ >+static void >+attach_selinux_data_edit_field (GtkEntry *entry, >+ char *attr_val, char *def_attr_val) >+{ >+ GtkEntryCompletion *comp; >+ GtkCellRenderer *cell; >+ const char *attr_u; >+ const char *attr_r; >+ const char *attr_t; >+ const char *attr_s; >+ const char *dattr_u; >+ const char *dattr_r; >+ const char *dattr_t; >+ const char *dattr_s; >+ GtkListStore *store; >+ GtkTreeIter iter; >+ GSList *scan; >+ int width; >+ int owidth; >+ int twidth; >+ >+ attr_val = g_strdup (attr_val); /* so we can alter it... */ >+ def_attr_val = g_strdup (def_attr_val); /* so we can alter it... */ >+ >+ /* do completion, so you don't have to type everything... */ >+ comp = gtk_entry_completion_new (); >+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); >+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), >+ 0, GTK_SORT_ASCENDING); >+ >+ gtk_entry_completion_set_model (comp, GTK_TREE_MODEL (store)); >+ cell = gtk_cell_renderer_pixbuf_new (); >+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp), cell, FALSE); >+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comp), cell, >+ "stock-id", 1, NULL); >+ gtk_entry_completion_set_text_column (comp, 0); >+ gtk_entry_set_completion (entry, comp); >+ >+ /* FIXME: default doesn't do the right thing, should it? */ >+ owidth = gtk_entry_get_width_chars (entry); >+ width = owidth; >+ >+ selinux_split_cntx (attr_val, &attr_u, &attr_r, &attr_t, &attr_s); >+ dattr_u = dattr_r = dattr_t = dattr_s = NULL; >+ if (def_attr_val) { >+ selinux_split_cntx (def_attr_val, &dattr_u, &dattr_r, >+ &dattr_t, &dattr_s); >+ } >+ >+ /* don't do it twice... */ >+ if (attr_t && dattr_t && !strcmp (attr_t, dattr_t)) { >+ dattr_t = NULL; >+ } >+ >+ if (attr_t) { >+ /* highlight just the type to the end, so we can easily change it >+ * FIXME: we also highlight any Sensitivity/MCS but completion will >+ * let people put it back, and that's the only way we get completion >+ * at all -- This sucks and we need to remove Sensitivity/MCS from >+ * the edit box. Yah, more UI. */ >+ int beg = attr_t - attr_u; >+ gtk_editable_select_region (GTK_EDITABLE (entry), beg, -1); >+ } >+ >+ for (scan = selinux__type_list(); scan; scan = scan->next) { >+ char *tmp; >+ >+ if (attr_t && !strcmp (attr_t, scan->data)) >+ continue; /* don't have two entries */ >+ >+ if (dattr_t && !strcmp (dattr_t, scan->data)) >+ continue; /* don't have two entries */ >+ >+ gtk_list_store_append (store, &iter); >+ tmp = g_strjoin (":", attr_u, attr_r, scan->data, attr_s, NULL); >+ gtk_list_store_set (store, &iter, 0, tmp, -1); >+ >+ twidth = strlen (tmp); >+ width = MAX (twidth, width); >+ >+ g_free (tmp); >+ } >+ >+ if (dattr_t) { >+ char *tmp; >+ >+ gtk_list_store_append (store, &iter); >+ tmp = g_strjoin (":", dattr_u, dattr_r, dattr_t, dattr_s, NULL); >+ gtk_list_store_set (store, &iter, 0, tmp, >+ 1, GTK_STOCK_HOME, -1); >+ >+ twidth = strlen (tmp); >+ width = MAX (twidth, width); >+ >+ g_free (tmp); >+ } >+ >+ if (attr_t) { >+ char *tmp; >+ >+ gtk_list_store_append (store, &iter); >+ tmp = g_strjoin (":", attr_u, attr_r, attr_t, attr_s, NULL); >+ gtk_list_store_set (store, &iter, 0, tmp, 1, GTK_STOCK_OK, -1); >+ >+ twidth = strlen (tmp); >+ width = MAX (twidth, width); >+ >+ g_free (tmp); >+ } >+ >+ g_free (attr_val); >+ g_free (def_attr_val); >+ g_object_unref (G_OBJECT (store)); >+ g_object_unref (G_OBJECT (comp)); >+ >+ if (width != owidth) { >+ gtk_entry_set_width_chars (entry, width + 2); >+ } >+} >+ >+# define HACK_TYPE(x, y) \ >+ else if (!strcmp (nice_type, x)) nice_type = y >+ >+/* hack to convert a selinux_context type into a readable string for the >+ user */ >+static const char * >+selinux__hack_conv_type (const char *type) >+{ /* FIXME: hack attack, but nowhere else to put it. Because mathpathcon >+ * here now probably want a bunch of other types? */ >+ const char *nice_type; >+ >+ nice_type = type; >+ >+ if (0) { } >+ >+ HACK_TYPE("cupsd_etc_t", _("CUPS printer configuration")); >+ HACK_TYPE("cupsd_rw_etc_t", _("CUPS printer configuration (rw)")); >+ HACK_TYPE("cupsd_tmp_t", _("CUPS temporary data")); >+ HACK_TYPE("dhcp_etc_t", _("DHCP configuration")); >+ HACK_TYPE("dictd_etc_t", _("Dictd configuration")); >+ HACK_TYPE("dnssec_t", _("DNS secret")); >+ HACK_TYPE("etc_t", _("System configuration")); >+ HACK_TYPE("etc_aliases_t", _("Email aliases configuration")); >+ HACK_TYPE("etc_runtime_t", _("System configuration (rw)")); >+ HACK_TYPE("cvs_data_t", _("Read and write from CVS daemon")); >+ HACK_TYPE("httpd_config_t", _("Apache-httpd configuration")); >+ HACK_TYPE("httpd_php_tmp_t", >+ _("Apache-httpd PHP module temporary data")); >+ HACK_TYPE("httpd_sys_content_t", >+ _("Read from all httpd scripts and the daemon")); >+ HACK_TYPE("httpd_sys_htaccess_t", >+ _("Apache-httpd .htaccess configuration")); >+ HACK_TYPE("httpd_sys_script_exec_t", >+ _("CGI programs with default access")); >+ HACK_TYPE("httpd_sys_script_ra_t", >+ _("CGI programs can read and append")); >+ HACK_TYPE("httpd_sys_script_ro_t", >+ _("CGI programs can read")); >+ HACK_TYPE("httpd_sys_script_rw_t", >+ _("CGI programs can read and write")); >+ HACK_TYPE("httpd_unconfined_script_exec_t", >+ _("CGI programs without any SELinux protection")); >+ HACK_TYPE("httpd_tmp_t", _("Apache-httpd temporary data")); >+ HACK_TYPE("ice_tmp_t", _("ICE temporary data")); >+ HACK_TYPE("locale_t", _("Locale data")); >+ HACK_TYPE("mysql_tmp_t", _("MySQL temporary data")); >+ HACK_TYPE("named_conf_t", _("Nameserver configuration")); >+ HACK_TYPE("net_conf_t", _("Network configuration")); >+ HACK_TYPE("postgresql_tmp_t", _("Postgresql temporary data")); >+ HACK_TYPE("public_content_rw_t", >+ _("Read and write from CIFS/ftp/http/nfs/rsync")); >+ HACK_TYPE("public_content_t", _("Read from CIFS/ftp/http/nfs/rsync")); >+ HACK_TYPE("samba_etc_t", _("Samba configuration")); >+ HACK_TYPE("samba_share_t", _("Shared via CIFS (samba)")); >+ HACK_TYPE("staff_home_t", _("Staff user data")); >+ HACK_TYPE("staff_home_dir_t", _("Staff user home directory")); >+ HACK_TYPE("swapfile_t", _("System swapfile")); >+ HACK_TYPE("sysadm_home_t", _("Sysadmin user data")); >+ HACK_TYPE("sysadm_home_dir_t", _("Sysadmin user home directory")); >+ HACK_TYPE("system_cron_spool_t", _("Cron data")); >+ HACK_TYPE("tmp_t", _("Temporary data")); >+ HACK_TYPE("user_tmp_t", _("User temporary data")); >+ HACK_TYPE("user_home_t", _("User data")); >+ HACK_TYPE("user_home_dir_t", _("User home directory")); >+ HACK_TYPE("var_log_t", _("Logfile")); >+ HACK_TYPE("xen_image_t", _("Xen image")); >+ >+ return nice_type; >+} >+#undef HACK_TYPE >+ >+static void >+attach_selinux_data_popup_field (GtkComboBox *comb, >+ char *attr_val, >+ char *def_attr_val) >+{ >+ const char *attr_u; >+ const char *attr_r; >+ const char *attr_t; >+ const char *attr_s; >+ const char *dattr_u; >+ const char *dattr_r; >+ const char *dattr_t; >+ const char *dattr_s; >+ GtkListStore *store; >+ GtkTreeIter iter; >+ GSList *scan; >+ >+ attr_val = g_strdup (attr_val); /* so we can alter it... */ >+ def_attr_val = g_strdup (def_attr_val); >+ >+ /* do completion, so you don't have to type everything... */ >+ store = gtk_list_store_new (3, G_TYPE_STRING, >+ G_TYPE_STRING, G_TYPE_STRING); >+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), >+ 1, GTK_SORT_ASCENDING); >+ >+ gtk_combo_box_set_model (comb, GTK_TREE_MODEL (store)); >+ >+ selinux_split_cntx (attr_val, &attr_u, &attr_r, &attr_t, &attr_s); >+ dattr_u = dattr_r = dattr_t = dattr_s = NULL; >+ if (def_attr_val) { >+ selinux_split_cntx (def_attr_val, &dattr_u, &dattr_r, >+ &dattr_t, &dattr_s); >+ } >+ /* don't do it twice... */ >+ if (attr_t && dattr_t && !strcmp (attr_t, dattr_t)) { >+ dattr_t = NULL; >+ } >+ >+ for (scan = selinux__type_list(); scan; scan = scan->next) { >+ const char *nice_type; >+ >+ if (attr_t && !strcmp (attr_t, scan->data)) >+ continue; /* don't have two entries */ >+ >+ if (dattr_t && !strcmp (dattr_t, scan->data)) >+ continue; /* don't have two entries */ >+ >+ nice_type = selinux__hack_conv_type(scan->data); >+ >+ gtk_list_store_append (store, &iter); >+ gtk_list_store_set (store, &iter, 0, scan->data, >+ 1, nice_type, -1); >+ } >+ >+ if (dattr_t) { >+ const char *nice_type; >+ >+ gtk_list_store_append (store, &iter); >+ nice_type = selinux__hack_conv_type(dattr_t); >+ gtk_list_store_set (store, &iter, 0, dattr_t, 1, nice_type, >+ 2, GTK_STOCK_HOME, -1); >+ } >+ >+ if (attr_t) { >+ const char *nice_type; >+ >+ gtk_list_store_append (store, &iter); >+ nice_type = selinux__hack_conv_type(attr_t); >+ gtk_list_store_set (store, &iter, 0, attr_t, 1, nice_type, >+ 2, GTK_STOCK_OK, -1); >+ gtk_combo_box_set_active_iter (comb, &iter); >+ } >+ >+ g_free (attr_val); >+ g_free (def_attr_val); >+ g_object_unref (G_OBJECT (store)); >+} >+ >+static char * >+selinux__matchpathcon (GList *file_list) >+{ >+ GList *scan; >+ >+ for (scan = file_list; scan != NULL; scan = scan->next) { >+ NautilusFile *file; >+ >+ file = NAUTILUS_FILE (scan->data); >+ if (!nautilus_file_is_gone (file)) { >+ return nautilus_file_get_selinux_matchpathcon (file); >+ } >+ } >+ >+ return NULL; >+} >+ >+static void >+attach_selinux_edit_field (FMPropertiesWindow *window, >+ GtkTable *table, >+ int row, >+ int column, >+ const char *file_attribute_name, >+ const char *inconsistent_string, >+ gboolean show_original, >+ GtkLabel *lab_title) >+{ >+ GtkEntry *entry; >+ GList *file_list; >+ char *attr_value; >+ char *def_attr_value; >+ >+ if (show_original) { >+ file_list = window->details->original_files; >+ } else { >+ file_list = window->details->target_files; >+ } >+ >+ attr_value = file_list_get_string_attribute (file_list, >+ file_attribute_name, >+ inconsistent_string); >+ if ( strcmp (attr_value, inconsistent_string) && >+ !strcmp (file_attribute_name, "selinux_context")) { >+ def_attr_value = selinux__matchpathcon (file_list); >+ } else { >+ def_attr_value = NULL; >+ } >+ >+ entry = attach_edit_label (table, row, column, attr_value); >+ gtk_label_set_mnemonic_widget (GTK_LABEL (lab_title), >+ GTK_WIDGET (entry)); >+ >+ /* Stash a copy of the file attribute name in this field for the callback's sake. */ >+ g_object_set_data_full (G_OBJECT (entry), "file_attribute", >+ g_strdup (file_attribute_name), g_free); >+ >+ g_object_set_data_full (G_OBJECT (entry), "inconsistent_string", >+ g_strdup (inconsistent_string), g_free); >+ >+ g_object_set_data (G_OBJECT (entry), "show_original", GINT_TO_POINTER (show_original)); >+ g_object_set_data (G_OBJECT (entry), "ellipsize_text", GINT_TO_POINTER (FALSE)); >+ >+ g_signal_connect_object (entry, "focus_out_event", >+ G_CALLBACK (selinux_focus_out), window, 0); >+ g_signal_connect_object (entry, "activate", >+ G_CALLBACK (selinux_entry_activate), window,0); >+ >+ attach_selinux_data_edit_field (entry, attr_value, def_attr_value); >+ >+ g_object_set_data_full (G_OBJECT (entry), "original_cntx", attr_value, >+ g_free); >+ >+ g_object_set_data_full (G_OBJECT (entry), "matchpathcon_cntx", >+ def_attr_value, g_free); >+ >+ window->details->edit_fields = g_list_prepend (window->details->edit_fields, >+ entry); >+} >+ >+static void >+attach_selinux_popup_field (FMPropertiesWindow *window, >+ GtkTable *table, >+ int row, >+ int column, >+ const char *file_attribute_name, >+ const char *inconsistent_string, >+ gboolean show_original, >+ GtkLabel *lab_title) >+{ >+ GtkWidget *comb; >+ GtkCellRenderer *cell; >+ GList *file_list; >+ char *attr_value; >+ char *def_attr_value; >+ >+ if (show_original) { >+ file_list = window->details->original_files; >+ } else { >+ file_list = window->details->target_files; >+ } >+ >+ attr_value = file_list_get_string_attribute (file_list, >+ file_attribute_name, >+ inconsistent_string); >+ if ( strcmp (attr_value, inconsistent_string) && >+ !strcmp (file_attribute_name, "selinux_context")) { >+ def_attr_value = selinux__matchpathcon (file_list); >+ } else { >+ def_attr_value = NULL; >+ } >+ >+ comb = gtk_combo_box_new (); >+ >+ gtk_table_attach (table, comb, column, column + 1, row, row + 1, >+ GTK_FILL, 0, 0, 0); >+ >+ >+ gtk_label_set_mnemonic_widget (GTK_LABEL (lab_title), comb); >+ >+ /* Stash a copy of the file attribute name in this field for the callback's sake. */ >+ g_object_set_data_full (G_OBJECT (comb), "file_attribute", >+ g_strdup (file_attribute_name), g_free); >+ >+ g_object_set_data (G_OBJECT (comb), "show_original", GINT_TO_POINTER (show_original)); >+ >+ attach_selinux_data_popup_field (GTK_COMBO_BOX (comb), >+ attr_value, def_attr_value); >+ >+ g_signal_connect_object (comb, "changed", >+ G_CALLBACK (selinux_popup_activate), window, 0); >+ >+ g_object_set_data_full (G_OBJECT (comb), "original_cntx", attr_value, >+ g_free); >+ >+ g_object_set_data_full (G_OBJECT (comb), "matchpathcon_cntx", >+ def_attr_value, g_free); >+ >+ cell = gtk_cell_renderer_pixbuf_new (); >+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comb), cell, FALSE); >+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comb), cell, >+ "stock-id", 2, NULL); >+ cell = gtk_cell_renderer_text_new (); >+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comb), cell, FALSE); >+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comb), cell, >+ "text", 1, NULL); >+ gtk_widget_show (comb); >+ >+ g_assert (! window->details->selinux_combo); >+ >+ window->details->selinux_combo = >+ g_list_prepend (window->details->selinux_combo, comb); >+} >+ > static GtkWidget* > attach_ellipsizing_value_field (FMPropertiesWindow *window, > GtkTable *table, >@@ -2441,6 +3314,36 @@ > } > > static guint >+append_title_selinux_edit_pair (FMPropertiesWindow *window, >+ GtkTable *table, >+ const char *title, >+ const char *file_attribute_name, >+ const char *inconsistent_state, >+ gboolean show_original) >+{ >+ guint last_row; >+ GtkLabel *lab_title; >+ >+ lab_title = NULL; >+ last_row = append_title_field (table, title, &lab_title); >+ >+ if (window->details->advanced_permissions) { >+ attach_selinux_edit_field (window, table, last_row, >+ VALUE_COLUMN, file_attribute_name, >+ inconsistent_state, >+ show_original, lab_title); >+ } else { >+ >+ attach_selinux_popup_field (window, table, last_row, >+ VALUE_COLUMN, file_attribute_name, >+ inconsistent_state, >+ show_original, lab_title); >+ } >+ >+ return last_row; >+} >+ >+static guint > append_title_and_ellipsizing_value (FMPropertiesWindow *window, > GtkTable *table, > const char *title, >@@ -2902,31 +3805,6 @@ > } > > static void >-start_long_operation (FMPropertiesWindow *window) >-{ >- if (window->details->long_operation_underway == 0) { >- /* start long operation */ >- GdkCursor * cursor; >- >- cursor = gdk_cursor_new (GDK_WATCH); >- gdk_window_set_cursor (GTK_WIDGET (window)->window, cursor); >- gdk_cursor_unref (cursor); >- } >- window->details->long_operation_underway ++; >-} >- >-static void >-end_long_operation (FMPropertiesWindow *window) >-{ >- if (GTK_WIDGET (window)->window != NULL && >- window->details->long_operation_underway == 1) { >- /* finished !! */ >- gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL); >- } >- window->details->long_operation_underway--; >-} >- >-static void > permission_change_callback (NautilusFile *file, GnomeVFSResult result, gpointer callback_data) > { > FMPropertiesWindow *window; >@@ -4053,14 +4931,16 @@ > GnomeVFSFilePermissions file_permission, file_permission_mask; > GnomeVFSFilePermissions dir_permission, dir_permission_mask; > GnomeVFSFilePermissions vfs_mask, vfs_new_perm, p; >- GtkWidget *button, *combo; >+ char *context; >+ GtkWidget *button; >+ GtkComboBox *combo; > gboolean active, is_folder, is_special, use_original; > GList *l; > GtkTreeModel *model; > GtkTreeIter iter; > PermissionType type; > int new_perm, mask; >- >+ > file_permission = 0; > file_permission_mask = 0; > dir_permission = 0; >@@ -4097,9 +4977,9 @@ > } > /* Simple mode, minus exec checkbox */ > for (l = window->details->permission_combos; l != NULL; l = l->next) { >- combo = l->data; >+ combo = GTK_COMBO_BOX (l->data); > >- if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) { >+ if (!gtk_combo_box_get_active_iter (combo, &iter)) { > continue; > } > >@@ -4107,7 +4987,7 @@ > is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), > "is-folder")); > >- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); >+ model = gtk_combo_box_get_model (combo); > gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1); > if (use_original) { > continue; >@@ -4130,12 +5010,53 @@ > } > } > >+ /* get the SELinux context... */ >+ context = NULL; >+ if (window->details->advanced_permissions && >+ window->details->edit_fields) { /* advanced mode */ >+ GtkEditable *efield; >+ >+ efield = window->details->edit_fields->data; >+ context = gtk_editable_get_chars (GTK_EDITABLE (efield), 0, -1); >+ } else if (!window->details->advanced_permissions && >+ window->details->selinux_combo) { /* simple mode */ >+ char *cntx_type; >+ char *orig_type; >+ const char *attr_u; >+ const char *attr_r; >+ const char *attr_t; >+ const char *attr_s; >+ >+ combo = GTK_COMBO_BOX (window->details->selinux_combo->data); >+ >+ if (!gtk_combo_box_get_active_iter (combo, &iter)) { >+ return; >+ } else { >+ GtkTreeModel *model = gtk_combo_box_get_model (combo); >+ gtk_tree_model_get (model, &iter, 0, &cntx_type, -1); >+ } >+ if (!(orig_type = g_object_get_data (G_OBJECT (combo), >+ "original_cntx"))) { >+ return; >+ } >+ >+ orig_type = g_strdup (orig_type); >+ >+ selinux_split_cntx (orig_type, >+ &attr_u, &attr_r, &attr_t, &attr_s); >+ context = g_strjoin (":", >+ attr_u, attr_r, cntx_type, attr_s, NULL); >+ g_free (orig_type); >+ } >+ > for (l = window->details->target_files; l != NULL; l = l->next) { > NautilusFile *file; > char *uri; > > file = NAUTILUS_FILE (l->data); > >+ /* assume permissions setting allows context setting... >+ * we can't really do much else due to race conditions anyway */ > if (nautilus_file_is_directory (file) && > nautilus_file_can_set_permissions (file)) { > uri = nautilus_file_get_uri (file); >@@ -4146,11 +5067,13 @@ > file_permission_mask, > dir_permission, > dir_permission_mask, >+ context, > set_recursive_permissions_done, > window); > g_free (uri); > } > } >+ g_free (context); > } > > static void >@@ -4197,11 +5120,20 @@ > } > > gtk_table_set_row_spacing (page_table, page_table->nrows - 1, 18); >- >- append_title_value_pair >- (window, page_table, _("SELinux Context:"), >- "selinux_context", _("--"), >- FALSE); >+ >+ if (!is_multi_file_window (window) || >+ multi_have_same_selinux_context (window)) >+ append_title_selinux_edit_pair >+ (window, page_table, _("_SELinux Context:"), >+ "selinux_context", _("--"), >+ FALSE); >+ else /* Static text in this case. */ >+ append_title_value_pair (window, page_table, >+ _("_SELinux Context:"), >+ "selinux_context", _("--"), >+ FALSE); >+ >+ > append_title_value_pair > (window, page_table, _("Last changed:"), > "date_permissions", _("--"),
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 223961
: 146283