1666 lines
48 KiB
Diff
1666 lines
48 KiB
Diff
|
--- nautilus-2.16.2/libnautilus-private/nautilus-file.c.selinux 2006-11-06 13:57:32.000000000 +0100
|
||
|
+++ nautilus-2.16.2/libnautilus-private/nautilus-file.c 2006-11-07 16:31:36.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,133 @@
|
||
|
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 (!strcmp(selinux_context, file->details->info->selinux_context)) {
|
||
|
+ (* 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 +3931,7 @@
|
||
|
GnomeVFSResult result,
|
||
|
GnomeVFSFileInfo *new_info,
|
||
|
gpointer callback_data)
|
||
|
-{
|
||
|
+{ /* FIXME: this is identical to set_permissions_callback */
|
||
|
Operation *op;
|
||
|
|
||
|
op = callback_data;
|
||
|
--- nautilus-2.16.2/libnautilus-private/nautilus-file.h.selinux 2006-10-02 12:46:28.000000000 +0200
|
||
|
+++ nautilus-2.16.2/libnautilus-private/nautilus-file.h 2006-11-07 16:31:36.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.16.2/libnautilus-private/nautilus-file-operations.c.selinux 2006-11-06 13:21:46.000000000 +0100
|
||
|
+++ nautilus-2.16.2/libnautilus-private/nautilus-file-operations.c 2006-11-07 16:31:36.000000000 +0100
|
||
|
@@ -62,6 +62,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;
|
||
|
@@ -2908,6 +2912,7 @@
|
||
|
GnomeVFSFilePermissions file_mask;
|
||
|
GnomeVFSFilePermissions dir_permissions;
|
||
|
GnomeVFSFilePermissions dir_mask;
|
||
|
+ char *context;
|
||
|
NautilusSetPermissionsCallback callback;
|
||
|
gpointer callback_data;
|
||
|
};
|
||
|
@@ -2935,6 +2940,8 @@
|
||
|
GnomeVFSURI *uri;
|
||
|
char *uri_str;
|
||
|
struct FileInfo *file_info;
|
||
|
+ int flags;
|
||
|
+ int options;
|
||
|
|
||
|
info = callback_data;
|
||
|
|
||
|
@@ -2965,10 +2972,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);
|
||
|
@@ -2976,7 +2991,6 @@
|
||
|
gnome_vfs_file_info_unref (vfs_info);
|
||
|
g_free (file_info->name);
|
||
|
g_free (file_info);
|
||
|
-
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -3021,13 +3035,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 */
|
||
|
@@ -3039,7 +3051,8 @@
|
||
|
{
|
||
|
struct RecursivePermissionsInfo *info;
|
||
|
char *uri_str;
|
||
|
-
|
||
|
+ int options;
|
||
|
+
|
||
|
info = callback_data;
|
||
|
|
||
|
if (result == GNOME_VFS_OK && handle != NULL) {
|
||
|
@@ -3048,9 +3061,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,
|
||
|
@@ -3062,6 +3079,8 @@
|
||
|
{
|
||
|
struct DirInfo *dir_info;
|
||
|
GnomeVFSFileInfo *vfs_info;
|
||
|
+ int flags;
|
||
|
+ int options;
|
||
|
|
||
|
gnome_vfs_uri_unref (info->current_dir);
|
||
|
|
||
|
@@ -3069,6 +3088,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;
|
||
|
}
|
||
|
@@ -3083,12 +3103,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);
|
||
|
@@ -3103,6 +3129,7 @@
|
||
|
GnomeVFSFilePermissions file_mask,
|
||
|
GnomeVFSFilePermissions dir_permissions,
|
||
|
GnomeVFSFilePermissions dir_mask,
|
||
|
+ const char *context,
|
||
|
NautilusSetPermissionsCallback callback,
|
||
|
gpointer callback_data)
|
||
|
{
|
||
|
@@ -3116,6 +3143,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;
|
||
|
|
||
|
@@ -3123,6 +3166,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.16.2/libnautilus-private/nautilus-file-operations.h.selinux 2006-10-02 12:46:28.000000000 +0200
|
||
|
+++ nautilus-2.16.2/libnautilus-private/nautilus-file-operations.h 2006-11-07 16:31:36.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.16.2/src/file-manager/fm-error-reporting.c.selinux 2006-10-02 12:46:28.000000000 +0200
|
||
|
+++ nautilus-2.16.2/src/file-manager/fm-error-reporting.c 2006-11-07 16:31:36.000000000 +0100
|
||
|
@@ -251,6 +251,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.16.2/src/file-manager/fm-error-reporting.h.selinux 2006-10-02 12:46:28.000000000 +0200
|
||
|
+++ nautilus-2.16.2/src/file-manager/fm-error-reporting.h 2006-11-07 16:31:36.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.16.2/src/file-manager/fm-properties-window.c.selinux 2006-10-31 10:21:41.000000000 +0100
|
||
|
+++ nautilus-2.16.2/src/file-manager/fm-properties-window.c 2006-11-07 16:41:59.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)
|
||
|
{
|
||
|
@@ -494,7 +560,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');
|
||
|
|
||
|
|
||
|
@@ -575,7 +641,7 @@
|
||
|
|
||
|
static void
|
||
|
set_name_field (FMPropertiesWindow *window, const gchar *original_name,
|
||
|
- const gchar *name)
|
||
|
+ const gchar *name)
|
||
|
{
|
||
|
gboolean new_widget;
|
||
|
gboolean use_label;
|
||
|
@@ -641,11 +707,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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -721,7 +783,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");
|
||
|
@@ -730,14 +791,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
|
||
|
@@ -850,7 +905,7 @@
|
||
|
word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp);
|
||
|
eel_g_list_free_deep (keywords);
|
||
|
|
||
|
- return (word != NULL);
|
||
|
+ return word != NULL;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -1117,7 +1172,7 @@
|
||
|
b = b->next;
|
||
|
}
|
||
|
|
||
|
- return (a == b);
|
||
|
+ return a == b;
|
||
|
}
|
||
|
|
||
|
static GList *
|
||
|
@@ -1199,6 +1254,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);
|
||
|
@@ -1379,6 +1442,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,
|
||
|
@@ -1430,6 +1598,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,
|
||
|
@@ -1489,6 +1696,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,
|
||
|
@@ -2439,6 +3312,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,
|
||
|
@@ -2900,31 +3803,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;
|
||
|
@@ -4051,14 +4929,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;
|
||
|
@@ -4095,9 +4975,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;
|
||
|
}
|
||
|
|
||
|
@@ -4105,7 +4985,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;
|
||
|
@@ -4128,12 +5008,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);
|
||
|
@@ -4144,11 +5065,13 @@
|
||
|
file_permission_mask,
|
||
|
dir_permission,
|
||
|
dir_permission_mask,
|
||
|
+ context,
|
||
|
set_recursive_permissions_done,
|
||
|
window);
|
||
|
g_free (uri);
|
||
|
}
|
||
|
}
|
||
|
+ g_free (context);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -4195,11 +5118,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", _("--"),
|