nautilus/nautilus-2.23.5-selinux.patch
Matthias Clasen 0aa6e375f3 2.23.5
2008-07-22 04:47:51 +00:00

1763 lines
53 KiB
Diff

diff -up nautilus-2.23.5/libnautilus-extension/nautilus-column.c.selinux nautilus-2.23.5/libnautilus-extension/nautilus-column.c
--- nautilus-2.23.5/libnautilus-extension/nautilus-column.c.selinux 2008-01-30 09:45:57.000000000 -0500
+++ nautilus-2.23.5/libnautilus-extension/nautilus-column.c 2008-07-22 00:35:23.000000000 -0400
@@ -34,6 +34,7 @@ enum {
PROP_LABEL,
PROP_DESCRIPTION,
PROP_XALIGN,
+ PROP_ELLIPSIZE,
LAST_PROP
};
@@ -43,6 +44,7 @@ struct _NautilusColumnDetails {
char *label;
char *description;
float xalign;
+ gboolean ellipsize;
};
static GObjectClass *parent_class = NULL;
@@ -99,6 +101,9 @@ nautilus_column_get_property (GObject *o
case PROP_XALIGN :
g_value_set_float (value, column->details->xalign);
break;
+ case PROP_ELLIPSIZE :
+ g_value_set_boolean (value, column->details->ellipsize);
+ break;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -140,6 +145,10 @@ nautilus_column_set_property (GObject *o
column->details->xalign = g_value_get_float (value);
g_object_notify (object, "xalign");
break;
+ case PROP_ELLIPSIZE :
+ column->details->ellipsize = g_value_get_boolean (value);
+ g_object_notify (object, "ellipsize");
+ break;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -167,6 +176,7 @@ nautilus_column_instance_init (NautilusC
{
column->details = g_new0 (NautilusColumnDetails, 1);
column->details->xalign = 0.0;
+ column->details->ellipsize = FALSE;
}
static void
@@ -223,6 +233,13 @@ nautilus_column_class_init (NautilusColu
1.0,
0.0,
G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ELLIPSIZE,
+ g_param_spec_boolean ("ellipsize",
+ "ellipsize",
+ "Ellipsize text in the column if it's too long to display",
+ FALSE,
+ G_PARAM_READWRITE));
}
GType
diff -up nautilus-2.23.5/libnautilus-extension/nautilus-column.h.selinux nautilus-2.23.5/libnautilus-extension/nautilus-column.h
--- nautilus-2.23.5/libnautilus-extension/nautilus-column.h.selinux 2006-12-30 18:16:39.000000000 -0500
+++ nautilus-2.23.5/libnautilus-extension/nautilus-column.h 2008-07-22 00:35:23.000000000 -0400
@@ -64,6 +64,7 @@ NautilusColumn * nautilus_column_new
* label (string) - the user-visible label for the column
* description (string) - a user-visible description of the column
* xalign (float) - x-alignment of the column
+ * ellipsize (boolean) - ellipsize text in the column?
*/
G_END_DECLS
diff -up nautilus-2.23.5/libnautilus-private/nautilus-column-utilities.c.selinux nautilus-2.23.5/libnautilus-private/nautilus-column-utilities.c
--- nautilus-2.23.5/libnautilus-private/nautilus-column-utilities.c.selinux 2008-06-30 12:02:26.000000000 -0400
+++ nautilus-2.23.5/libnautilus-private/nautilus-column-utilities.c 2008-07-22 00:35:23.000000000 -0400
@@ -119,6 +119,7 @@ get_builtin_columns (void)
"attribute", "selinux_context",
"label", _("SELinux Context"),
"description", _("The SELinux security context of the file."),
+ "ellipsize", TRUE,
NULL));
return columns;
diff -up nautilus-2.23.5/libnautilus-private/nautilus-file.c.selinux nautilus-2.23.5/libnautilus-private/nautilus-file.c
--- nautilus-2.23.5/libnautilus-private/nautilus-file.c.selinux 2008-07-21 10:01:22.000000000 -0400
+++ nautilus-2.23.5/libnautilus-private/nautilus-file.c 2008-07-22 00:35:23.000000000 -0400
@@ -1647,7 +1647,7 @@ update_info_internal (NautilusFile *file
file->details->is_mountpoint = is_mountpoint;
has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE);
- permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);;
+ permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);
if (file->details->has_permissions != has_permissions ||
file->details->permissions != permissions) {
changed = TRUE;
@@ -4300,7 +4300,7 @@ nautilus_file_can_get_selinux_context (N
* 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 *
@@ -4333,6 +4333,114 @@ nautilus_file_get_selinux_context (Nauti
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;
+#ifdef HAVE_SELINUX
+ char *raw;
+ char *fname;
+ GFile *location;
+#endif
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
+
+ translated = NULL;
+#ifdef HAVE_SELINUX
+ location = nautilus_file_get_location (file);
+ fname = g_file_get_path (location);
+
+ if (!fname) {
+ return NULL;
+ }
+
+ raw = NULL;
+ if (matchpathcon (fname, file->details->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_object_unref (location);
+#endif
+
+ return translated;
+}
+
+void
+nautilus_file_set_selinux_context (NautilusFile *file,
+ const char *selinux_context,
+ NautilusFileOperationCallback callback,
+ gpointer callback_data)
+{
+ GFileInfo *info;
+ GError *error;
+ 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);
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Not allowed to set SELinux security context"));
+ (* callback) (file, NULL, error, callback_data);
+ g_error_free (error);
+ 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->selinux_context != NULL &&
+ strcmp(selinux_context, file->details->selinux_context) == 0) {
+ (* callback) (file, NULL, NULL, 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)) {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVAL,
+ _("Invalid SELinux security context"));
+ (* callback) (file, NULL, error, callback_data);
+ g_error_free (error);
+ return;
+ }
+ selinux_context = rcontext;
+#endif
+
+ info = g_file_info_new ();
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT, selinux_context);
+ nautilus_file_set_attributes (file, info, callback, callback_data);
+ g_object_unref (info);
+
+#ifdef HAVE_SELINUX
+ freecon (rcontext);
+#endif
+}
+
+
static char *
get_real_name (const char *name, const char *gecos)
{
diff -up nautilus-2.23.5/libnautilus-private/nautilus-file.h.selinux nautilus-2.23.5/libnautilus-private/nautilus-file.h
--- nautilus-2.23.5/libnautilus-private/nautilus-file.h.selinux 2008-07-21 08:29:41.000000000 -0400
+++ nautilus-2.23.5/libnautilus-private/nautilus-file.h 2008-07-22 00:35:23.000000000 -0400
@@ -244,6 +244,7 @@ GList * nautilus_get_all
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);
@@ -278,6 +279,10 @@ void nautilus_file_se
guint32 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,
diff -up nautilus-2.23.5/libnautilus-private/nautilus-file-operations.c.selinux nautilus-2.23.5/libnautilus-private/nautilus-file-operations.c
--- nautilus-2.23.5/libnautilus-private/nautilus-file-operations.c.selinux 2008-07-21 11:28:42.000000000 -0400
+++ nautilus-2.23.5/libnautilus-private/nautilus-file-operations.c 2008-07-22 00:35:23.000000000 -0400
@@ -64,6 +64,11 @@
#include "nautilus-trash-monitor.h"
#include "nautilus-file-utilities.h"
+#ifdef HAVE_SELINUX
+ #include <selinux/selinux.h>
+#endif
+
+
static gboolean confirm_trash_auto_value;
/* TODO: TESTING!!! */
@@ -137,6 +142,7 @@ typedef struct {
guint32 file_mask;
guint32 dir_permissions;
guint32 dir_mask;
+ char *context;
} SetPermissionsJob;
typedef enum {
@@ -4742,6 +4748,10 @@ set_permissions_job_done (gpointer user_
job->done_callback (job->done_callback_data);
}
+ if (job->context) {
+ g_free (job->context);
+ }
+
finalize_common ((CommonJob *)job);
return FALSE;
}
@@ -4797,6 +4807,14 @@ set_permissions_file (SetPermissionsJob
current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
common->cancellable, NULL);
}
+
+#ifdef HAVE_SELINUX
+ if (!job_aborted (common) && (job->context)) {
+ g_file_set_attribute_string (file, G_FILE_ATTRIBUTE_SELINUX_CONTEXT,
+ job->context, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ common->cancellable, NULL);
+ }
+#endif
if (!job_aborted (common) &&
g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
@@ -4860,6 +4878,7 @@ nautilus_file_set_permissions_recursive
guint32 file_mask,
guint32 dir_permissions,
guint32 dir_mask,
+ const char *context,
NautilusOpCallback callback,
gpointer callback_data)
{
@@ -4873,7 +4892,24 @@ nautilus_file_set_permissions_recursive
job->dir_mask = dir_mask;
job->done_callback = callback;
job->done_callback_data = callback_data;
-
+
+ if (context) {
+ char *rcontext;
+
+ rcontext = job->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;
+ }
+ job->context = g_strdup (rcontext);
+ freecon (rcontext);
+#endif
+ } else {
+ job->context = NULL;
+ }
+
g_io_scheduler_push_job (set_permissions_job,
job,
NULL,
diff -up nautilus-2.23.5/libnautilus-private/nautilus-file-operations.h.selinux nautilus-2.23.5/libnautilus-private/nautilus-file-operations.h
--- nautilus-2.23.5/libnautilus-private/nautilus-file-operations.h.selinux 2008-07-21 08:27:39.000000000 -0400
+++ nautilus-2.23.5/libnautilus-private/nautilus-file-operations.h 2008-07-22 00:35:23.000000000 -0400
@@ -85,6 +85,7 @@ void nautilus_file_set_permissions_recur
guint32 file_mask,
guint32 folder_permissions,
guint32 folder_mask,
+ const char *context,
NautilusOpCallback callback,
gpointer callback_data);
diff -up nautilus-2.23.5/src/file-manager/fm-error-reporting.c.selinux nautilus-2.23.5/src/file-manager/fm-error-reporting.c
--- nautilus-2.23.5/src/file-manager/fm-error-reporting.c.selinux 2008-06-30 13:07:19.000000000 -0400
+++ nautilus-2.23.5/src/file-manager/fm-error-reporting.c 2008-07-22 00:35:23.000000000 -0400
@@ -232,6 +232,31 @@ fm_report_error_setting_permissions (Nau
g_free (message);
}
+void
+fm_report_error_setting_selinux (NautilusFile *file,
+ GError *error,
+ GtkWindow *parent_window)
+{
+ char *file_name;
+ char *message;
+
+ if (error == NULL) {
+ return;
+ }
+
+ file_name = nautilus_file_get_display_name (file);
+
+ message = g_strdup_printf (_("Sorry, couldn't change the permissions of \"%s\": %s"), file_name, error->message);
+
+ /* Silently drop the error when called from selinux entry and is not finished yet */
+ if (! g_error_matches(error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT)) {
+ 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;
diff -up nautilus-2.23.5/src/file-manager/fm-error-reporting.h.selinux nautilus-2.23.5/src/file-manager/fm-error-reporting.h
--- nautilus-2.23.5/src/file-manager/fm-error-reporting.h.selinux 2008-06-30 13:07:19.000000000 -0400
+++ nautilus-2.23.5/src/file-manager/fm-error-reporting.h 2008-07-22 00:35:23.000000000 -0400
@@ -41,8 +41,11 @@ void fm_report_error_setting_permissions
GError *error,
GtkWindow *parent_window);
void fm_report_error_setting_owner (NautilusFile *file,
- GError *error,
+ GError *error,
GtkWindow *parent_window);
+void fm_report_error_setting_selinux (NautilusFile *file,
+ GError *error,
+ GtkWindow *parent_window);
void fm_report_error_setting_group (NautilusFile *file,
GError *error,
GtkWindow *parent_window);
diff -up nautilus-2.23.5/src/file-manager/fm-list-view.c.selinux nautilus-2.23.5/src/file-manager/fm-list-view.c
--- nautilus-2.23.5/src/file-manager/fm-list-view.c.selinux 2008-07-21 05:53:43.000000000 -0400
+++ nautilus-2.23.5/src/file-manager/fm-list-view.c 2008-07-22 00:35:23.000000000 -0400
@@ -1378,13 +1378,15 @@ create_and_set_up_tree_view (FMListView
char *name;
char *label;
float xalign;
+ gboolean ellipsize;
nautilus_column = NAUTILUS_COLUMN (l->data);
g_object_get (nautilus_column,
"name", &name,
"label", &label,
- "xalign", &xalign, NULL);
+ "xalign", &xalign,
+ "ellipsize", &ellipsize, NULL);
column_num = fm_list_model_add_column (view->details->model,
nautilus_column);
@@ -1430,6 +1432,8 @@ create_and_set_up_tree_view (FMListView
} else {
cell = gtk_cell_renderer_text_new ();
g_object_set (cell, "xalign", xalign, NULL);
+ if (ellipsize)
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
view->details->cells = g_list_append (view->details->cells,
cell);
column = gtk_tree_view_column_new_with_attributes (label,
diff -up nautilus-2.23.5/src/file-manager/fm-properties-window.c.selinux nautilus-2.23.5/src/file-manager/fm-properties-window.c
--- nautilus-2.23.5/src/file-manager/fm-properties-window.c.selinux 2008-07-21 11:28:42.000000000 -0400
+++ nautilus-2.23.5/src/file-manager/fm-properties-window.c 2008-07-22 00:39:19.000000000 -0400
@@ -83,6 +83,10 @@
#define FREE_FILL_B (0.811764706 * 65535)
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h>
+#endif
+
#define PREVIEW_IMAGE_WIDTH 96
#define ROW_PAD 6
@@ -125,12 +129,15 @@ struct FMPropertiesWindowDetails {
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;
@@ -217,6 +224,10 @@ static void permission_combo_update
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,
@@ -246,10 +257,36 @@ static GtkLabel *attach_ellipsizing_valu
const char *initial_text);
static GtkWidget* create_pie_widget (FMPropertiesWindow *window);
+
+static void attach_selinux_data_edit_field (GtkEntry *entry,
+ char *attr_value,
+ char *def_attr_value);
+
+#ifdef HAVE_SELINUX
+static void attach_selinux_data_popup_field (GtkComboBox *comb,
+ char *attr_val,
+ char *def_attr_val);
+#endif
+
G_DEFINE_TYPE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_DIALOG);
#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)
{
@@ -270,6 +307,111 @@ is_multi_file_window (FMPropertiesWindow
return FALSE;
}
+static gboolean
+all_can_get_permissions (GList *file_list)
+{
+ GList *l;
+ for (l = file_list; l != NULL; l = l->next) {
+ NautilusFile *file;
+
+ file = NAUTILUS_FILE (l->data);
+
+ if (!nautilus_file_can_get_permissions (file)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+all_can_set_permissions (GList *file_list)
+{
+ GList *l;
+ for (l = file_list; l != NULL; l = l->next) {
+ NautilusFile *file;
+
+ file = NAUTILUS_FILE (l->data);
+
+ if (!nautilus_file_can_set_permissions (file)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+#ifdef HAVE_SELINUX
+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;
+}
+#endif
+
+/* 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 int
get_not_gone_original_file_count (FMPropertiesWindow *window)
{
@@ -502,7 +644,7 @@ fm_properties_window_drag_data_received
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');
@@ -651,11 +793,7 @@ set_name_field (FMPropertiesWindow *wind
* 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);
}
}
}
@@ -735,7 +873,6 @@ static void
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");
@@ -744,14 +881,8 @@ name_field_restore_original_name (Nautil
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
@@ -1213,6 +1344,14 @@ properties_window_update (FMPropertiesWi
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);
@@ -1383,6 +1522,164 @@ value_field_update (FMPropertiesWindow *
window->details->target_files));
}
+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;
+ gboolean sensitive;
+
+ 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);
+
+ sensitive = all_can_set_permissions (file_list);
+#ifdef HAVE_SELINUX
+ sensitive = sensitive && is_selinux_enabled ();
+#endif
+ gtk_widget_set_sensitive (GTK_WIDGET (entry), sensitive);
+}
+
+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
+selinux_combo_update_value (GtkComboBox *combo, const char *new_value)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *cntx_type;
+ gulong handler;
+
+ g_assert (GTK_IS_COMBO_BOX (combo));
+ if (! new_value)
+ return;
+
+ model = gtk_combo_box_get_model (combo);
+ if (! gtk_tree_model_get_iter_first (model, &iter))
+ return;
+
+ handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (combo), "handler_changed"));
+ g_signal_handler_block (G_OBJECT (combo), handler);
+
+ do {
+ gtk_tree_model_get (model, &iter, 0, &cntx_type, -1);
+
+ if (cntx_type && (g_ascii_strcasecmp (new_value, cntx_type) == 0)) {
+ gtk_combo_box_set_active_iter (combo, &iter);
+ break;
+ }
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+ g_signal_handler_unblock (G_OBJECT (combo), handler);
+}
+
+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;
+ const char *attr_u;
+ const char *attr_r;
+ const char *attr_t;
+ const char *attr_s;
+ gboolean sensitive;
+ GtkTreeIter iter;
+
+
+ g_assert (GTK_IS_COMBO_BOX (combo));
+
+ if (gtk_widget_is_focus (GTK_WIDGET (combo))) {
+ return;
+ }
+
+
+ sensitive = all_can_set_permissions (file_list);
+#ifdef HAVE_SELINUX
+ sensitive = sensitive && is_selinux_enabled ();
+#endif
+ gtk_widget_set_sensitive (GTK_WIDGET (combo), sensitive);
+
+
+ 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);
+
+ selinux_split_cntx (attr_value, &attr_u, &attr_r, &attr_t, &attr_s);
+
+ /* 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_t) == 0) {
+ g_free (attr_value);
+ return;
+ }
+ }
+
+ selinux_combo_update_value (combo, attr_t);
+
+ g_free (attr_value);
+}
+
+static void
+popup_field_update (FMPropertiesWindow *window, GtkComboBox *combo)
+{
+ gboolean use_original;
+
+ if (! window->details->selinux_combo) {
+ return;
+ }
+
+ 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,
@@ -1437,6 +1734,47 @@ attach_value_label (GtkTable *table,
return attach_label (table, row, column, initial_text, FALSE, FALSE, FALSE, TRUE, FALSE);
}
+#ifdef HAVE_SELINUX
+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);
+}
+#endif
+
static GtkLabel *
attach_ellipsizing_value_label (GtkTable *table,
int row,
@@ -1495,6 +1833,649 @@ attach_value_field (FMPropertiesWindow *
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);
+ if (GDK_IS_WINDOW (GTK_WIDGET (window)->window)) {
+ 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--;
+}
+
+#ifdef HAVE_SELINUX
+static void
+selinux_change_callback (NautilusFile *file,
+ GFile *result_location,
+ GError *error,
+ 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, error, 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);
+}
+
+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;
+ GtkTreeModel *model;
+
+ 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 {
+ 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;
+}
+#endif
+
+static GSList *
+selinux__type_list (void)
+{
+ static GSList *cust_types;
+ GSList *scan;
+#ifdef HAVE_SELINUX
+ static time_t file_mtime;
+ const char *fname_ctypes;
+ struct stat buf;
+ GIOChannel *ioc_ctypes;
+ GError *errc;
+ int fd;
+#endif
+
+#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 && GTK_WIDGET_SENSITIVE (entry)) {
+ /* 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);
+ }
+}
+
+#ifdef HAVE_SELINUX
+
+# 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;
+ gulong handler;
+
+ 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));
+
+ 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);
+
+ attach_selinux_data_popup_field (GTK_COMBO_BOX (comb),
+ attr_value, def_attr_value);
+
+ handler = g_signal_connect_object (comb, "changed",
+ G_CALLBACK (selinux_popup_activate), window, 0);
+ g_object_set_data (G_OBJECT (comb), "handler_changed", GUINT_TO_POINTER (handler));
+
+ g_assert (! window->details->selinux_combo);
+
+ window->details->selinux_combo =
+ g_list_prepend (window->details->selinux_combo, comb);
+}
+#endif
+
static GtkWidget*
attach_ellipsizing_value_field (FMPropertiesWindow *window,
GtkTable *table,
@@ -2451,6 +3432,37 @@ append_title_value_pair (FMPropertiesWin
return last_row;
}
+#ifdef HAVE_SELINUX
+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;
+}
+#endif
+
static guint
append_title_and_ellipsizing_value (FMPropertiesWindow *window,
GtkTable *table,
@@ -3470,31 +4482,6 @@ create_emblems_page (FMPropertiesWindow
}
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,
GFile *res_loc,
GError *error,
@@ -4270,39 +5257,6 @@ append_special_execution_flags (FMProper
gtk_table_set_row_spacing (table, table->nrows - 1, 18);
}
-static gboolean
-all_can_get_permissions (GList *file_list)
-{
- GList *l;
- for (l = file_list; l != NULL; l = l->next) {
- NautilusFile *file;
-
- file = NAUTILUS_FILE (l->data);
-
- if (!nautilus_file_can_get_permissions (file)) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-all_can_set_permissions (GList *file_list)
-{
- GList *l;
- for (l = file_list; l != NULL; l = l->next) {
- NautilusFile *file;
-
- file = NAUTILUS_FILE (l->data);
-
- if (!nautilus_file_can_set_permissions (file)) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
static GHashTable *
get_initial_permissions (GList *file_list)
@@ -4642,7 +5596,9 @@ apply_recursive_clicked (GtkWidget *recu
guint32 file_permission, file_permission_mask;
guint32 dir_permission, dir_permission_mask;
guint32 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;
@@ -4686,9 +5642,9 @@ apply_recursive_clicked (GtkWidget *recu
}
/* 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;
}
@@ -4696,7 +5652,7 @@ apply_recursive_clicked (GtkWidget *recu
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;
@@ -4719,12 +5675,53 @@ apply_recursive_clicked (GtkWidget *recu
}
}
+ /* 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);
@@ -4735,11 +5732,13 @@ apply_recursive_clicked (GtkWidget *recu
file_permission_mask,
dir_permission,
dir_permission_mask,
+ context,
set_recursive_permissions_done,
window);
g_free (uri);
}
}
+ g_free (context);
}
static void
@@ -4788,10 +5787,16 @@ create_permissions_page (FMPropertiesWin
gtk_table_set_row_spacing (page_table, page_table->nrows - 1, 18);
#ifdef HAVE_SELINUX
- append_title_value_pair
- (window, page_table, _("SELinux context:"),
- "selinux_context", INCONSISTENT_STATE_STRING,
- 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", INCONSISTENT_STATE_STRING,
+ FALSE);
+ else /* Static text in this case. */
+ append_title_value_pair (window, page_table,
+ _("_SELinux Context:"),
+ "selinux_context", INCONSISTENT_STATE_STRING,
+ FALSE);
#endif
append_title_value_pair
(window, page_table, _("Last changed:"),