From 47be9ff57e72906660bb62a515222f482131e1fb Mon Sep 17 00:00:00 2001 From: Miroslav Grepl Date: Fri, 11 Apr 2014 09:37:53 +0200 Subject: Create setools-3.3.7 git repo --- seaudit/policy_components_view.c | 373 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 seaudit/policy_components_view.c (limited to 'seaudit/policy_components_view.c') diff --git a/seaudit/policy_components_view.c b/seaudit/policy_components_view.c new file mode 100644 index 0000000..c2f1d02 --- /dev/null +++ b/seaudit/policy_components_view.c @@ -0,0 +1,373 @@ +/** + * @file + * Run the dialog to select from lists of strings. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * + * Copyright (C) 2004-2007 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "policy_components_view.h" + +#include +#include +#include +#include +#include + +struct polcomp_view +{ + GladeXML *xml; + toplevel_t *top; + apol_vector_t *log_items, *policy_items, *both_items, *included_items; + GtkDialog *dialog; + + GtkRadioButton *log_radio, *policy_radio, *both_radio; + + GtkListStore *master_store; + GtkTreeModel *inc_store, *exc_store; + GtkTreeView *inc_view, *exc_view; + GtkButton *inc_select_button, *inc_unselect_button, *exc_select_button, *exc_unselect_button; + + GtkButton *to_exc_button, *to_inc_button; +}; + +enum polcom_columns +{ + POINTER_COLUMN = 0, NAME_COLUMN, ISLOG_COLUMN, ISPOLICY_COLUMN, ISINC_COLUMN +}; + +static void policy_components_view_init_widgets(struct polcomp_view *pv) +{ + pv->dialog = GTK_DIALOG(glade_xml_get_widget(pv->xml, "PolicyComponentListsWindow")); + assert(pv->dialog != NULL); + gtk_window_set_transient_for(GTK_WINDOW(pv->dialog), toplevel_get_window(pv->top)); + + pv->log_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompLogRadio")); + pv->policy_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompPolicyRadio")); + pv->both_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompBothRadio")); + assert(pv->log_radio != NULL && pv->policy_radio != NULL && pv->both_radio != NULL); + + pv->inc_view = GTK_TREE_VIEW(glade_xml_get_widget(pv->xml, "PolicyCompIncView")); + pv->exc_view = GTK_TREE_VIEW(glade_xml_get_widget(pv->xml, "PolicyCompExcView")); + assert(pv->inc_view != NULL && pv->exc_view != NULL); + + pv->inc_select_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompIncSelectButton")); + pv->inc_unselect_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompIncUnselectButton")); + pv->exc_select_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompExcSelectButton")); + pv->exc_unselect_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompExcUnselectButton")); + assert(pv->inc_select_button != NULL && pv->inc_unselect_button && + pv->exc_select_button != NULL && pv->exc_unselect_button); + + pv->to_exc_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompToExcButton")); + pv->to_inc_button = GTK_BUTTON(glade_xml_get_widget(pv->xml, "PolicyCompToIncButton")); + assert(pv->to_exc_button != NULL && pv->to_inc_button); +} + +/******************** functions to build the lists ********************/ + +/** + * Determine if a particular row should be visible based upon the + * current radio button selection. If the current item source is + * 'Log' then return TRUE if the islog attribute is enabled. If the + * source is 'Policy' then return TRUE if ispolicy is enabled. + * Otherwise the item is visible by default. + */ +static gboolean policy_components_view_is_visible_radio(struct polcomp_view *pv, gboolean islog, gboolean ispolicy) +{ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pv->log_radio))) { + return islog; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pv->policy_radio))) { + return ispolicy; + } + return TRUE; +} + +/** + * Callback invoked to determine if a row should be visible to the + * included view. + */ +static gboolean policy_components_view_is_visible_included(GtkTreeModel * model, GtkTreeIter * iter, gpointer data) +{ + struct polcomp_view *pv = (struct polcomp_view *)data; + gboolean islog, ispolicy, isinc; + gtk_tree_model_get(model, iter, ISLOG_COLUMN, &islog, ISPOLICY_COLUMN, &ispolicy, ISINC_COLUMN, &isinc, -1); + if (!isinc) { + return FALSE; + } + return policy_components_view_is_visible_radio(pv, islog, ispolicy); +} + +/** + * Callback invoked to determine if a row should be visible in the + * included view. + */ +static gboolean policy_components_view_is_visible_excluded(GtkTreeModel * model, GtkTreeIter * iter, gpointer data) +{ + struct polcomp_view *pv = (struct polcomp_view *)data; + gboolean islog, ispolicy, isinc; + gtk_tree_model_get(model, iter, ISLOG_COLUMN, &islog, ISPOLICY_COLUMN, &ispolicy, ISINC_COLUMN, &isinc, -1); + if (isinc) { + return FALSE; + } + return policy_components_view_is_visible_radio(pv, islog, ispolicy); +} + +static void policy_components_view_init_lists(struct polcomp_view *pv) +{ + GtkTreeIter iter; + size_t i, j; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkTreeSelection *selection; + + if ((pv->both_items = apol_vector_create_from_vector(pv->log_items, NULL, NULL, NULL)) == NULL) { + toplevel_ERR(pv->top, "Error generating union list: %s", strerror(errno)); + return; + } + if (pv->policy_items == NULL) { + gtk_widget_set_sensitive(GTK_WIDGET(pv->policy_radio), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(pv->both_radio), FALSE); + } else { + if (apol_vector_cat(pv->both_items, pv->policy_items) < 0) { + toplevel_ERR(pv->top, "Error generating union list: %s", strerror(errno)); + return; + } + apol_vector_sort_uniquify(pv->both_items, apol_str_strcmp, NULL); + } + pv->master_store = + gtk_list_store_new(ISINC_COLUMN + 1, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + for (i = 0; i < apol_vector_get_size(pv->both_items); i++) { + char *s = apol_vector_get_element(pv->both_items, i); + gboolean is_log = FALSE, is_policy = FALSE, is_included = FALSE; + if (apol_vector_get_index(pv->log_items, s, NULL, NULL, &j) == 0) { + is_log = TRUE; + } + if (pv->policy_items != NULL && apol_vector_get_index(pv->policy_items, s, NULL, NULL, &j) == 0) { + is_policy = TRUE; + } + if (apol_vector_get_index(pv->included_items, s, apol_str_strcmp, NULL, &j) == 0) { + is_included = TRUE; + } + gtk_list_store_append(pv->master_store, &iter); + gtk_list_store_set(pv->master_store, &iter, + POINTER_COLUMN, s, + NAME_COLUMN, s, ISLOG_COLUMN, is_log, ISPOLICY_COLUMN, is_policy, ISINC_COLUMN, is_included, -1); + } + + pv->inc_store = gtk_tree_model_filter_new(GTK_TREE_MODEL(pv->master_store), NULL); + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(pv->inc_store), policy_components_view_is_visible_included, pv, + NULL); + pv->exc_store = gtk_tree_model_filter_new(GTK_TREE_MODEL(pv->master_store), NULL); + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(pv->exc_store), policy_components_view_is_visible_excluded, pv, + NULL); + gtk_tree_view_set_model(pv->inc_view, pv->inc_store); + gtk_tree_view_set_model(pv->exc_view, pv->exc_store); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("Item names", renderer, "text", NAME_COLUMN, NULL); + gtk_tree_view_column_set_clickable(column, FALSE); + gtk_tree_view_column_set_resizable(column, FALSE); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_column_set_visible(column, TRUE); + gtk_tree_view_append_column(pv->inc_view, column); + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("Item names", renderer, "text", NAME_COLUMN, NULL); + gtk_tree_view_column_set_clickable(column, FALSE); + gtk_tree_view_column_set_resizable(column, FALSE); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_column_set_visible(column, TRUE); + gtk_tree_view_append_column(pv->exc_view, column); + + selection = gtk_tree_view_get_selection(pv->inc_view); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + selection = gtk_tree_view_get_selection(pv->exc_view); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); +} + +/******************** signal handlers ********************/ + +static void policy_components_view_on_source_toggle(GtkToggleButton * widget, gpointer user_data) +{ + struct polcomp_view *pv = (struct polcomp_view *)user_data; + /* clicking on the radio buttons emit two toggle signals, one for + * the original button and one for the new one. thus only need to + * handle half of all signals */ + if (!gtk_toggle_button_get_active(widget)) { + return; + } + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->inc_store)); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->exc_store)); +} + +static void policy_components_gtk_tree_path_free(gpointer data, gpointer user_data __attribute__ ((unused))) +{ + gtk_tree_path_free((GtkTreePath *) data); +} + +static void policy_components_gtk_tree_row_reference_free(gpointer data, gpointer user_data __attribute__ ((unused))) +{ + gtk_tree_row_reference_free((GtkTreeRowReference *) data); +} + +static void policy_components_view_on_to_exc_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data) +{ + struct polcomp_view *pv = (struct polcomp_view *)user_data; + GtkTreeSelection *selection = gtk_tree_view_get_selection(pv->inc_view); + GList *r, *rows = gtk_tree_selection_get_selected_rows(selection, NULL); + GList *refs = NULL; + + /* use references because the filtered store will be changing + * as master_store's ISINC_COLUMN value changes */ + for (r = rows; r != NULL; r = r->next) { + GtkTreePath *path = (GtkTreePath *) r->data; + GtkTreeRowReference *ref = gtk_tree_row_reference_new(pv->inc_store, path); + refs = g_list_prepend(refs, ref); + } + + for (r = refs; r != NULL; r = r->next) { + GtkTreeRowReference *ref = (GtkTreeRowReference *) r->data; + GtkTreePath *path = gtk_tree_row_reference_get_path(ref); + GtkTreeIter iter, child_iter; + char *name; + size_t i = 0; + int retval; + gtk_tree_model_get_iter(pv->inc_store, &iter, path); + gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(pv->inc_store), &child_iter, &iter); + gtk_tree_model_get(GTK_TREE_MODEL(pv->master_store), &child_iter, NAME_COLUMN, &name, -1); + gtk_list_store_set(pv->master_store, &child_iter, ISINC_COLUMN, FALSE, -1); + retval = apol_vector_get_index(pv->included_items, name, apol_str_strcmp, NULL, &i); + assert(retval == 0); + name = apol_vector_get_element(pv->included_items, i); + free(name); + apol_vector_remove(pv->included_items, i); + } + + g_list_foreach(refs, policy_components_gtk_tree_row_reference_free, NULL); + g_list_free(refs); + g_list_foreach(rows, policy_components_gtk_tree_path_free, NULL); + g_list_free(rows); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->inc_store)); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->exc_store)); +} + +static void policy_components_view_on_to_inc_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data) +{ + struct polcomp_view *pv = (struct polcomp_view *)user_data; + GtkTreeSelection *selection = gtk_tree_view_get_selection(pv->exc_view); + GList *r, *rows = gtk_tree_selection_get_selected_rows(selection, NULL); + + /* use references because the filtered store will be changing + * as master_store's ISINC_COLUMN value changes */ + GList *refs = NULL; + for (r = rows; r != NULL; r = r->next) { + GtkTreePath *path = (GtkTreePath *) r->data; + GtkTreeRowReference *ref = gtk_tree_row_reference_new(pv->exc_store, path); + refs = g_list_prepend(refs, ref); + } + + for (r = refs; r != NULL; r = r->next) { + GtkTreeRowReference *ref = (GtkTreeRowReference *) r->data; + GtkTreePath *path = gtk_tree_row_reference_get_path(ref); + GtkTreeIter iter, child_iter; + char *name; + gtk_tree_model_get_iter(pv->exc_store, &iter, path); + gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(pv->exc_store), &child_iter, &iter); + gtk_tree_model_get(GTK_TREE_MODEL(pv->master_store), &child_iter, NAME_COLUMN, &name, -1); + gtk_list_store_set(pv->master_store, &child_iter, ISINC_COLUMN, TRUE, -1); + apol_vector_append(pv->included_items, strdup(name)); + } + apol_vector_sort_uniquify(pv->included_items, apol_str_strcmp, NULL); + g_list_foreach(refs, policy_components_gtk_tree_row_reference_free, NULL); + g_list_free(refs); + g_list_foreach(rows, policy_components_gtk_tree_path_free, NULL); + g_list_free(rows); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->inc_store)); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(pv->exc_store)); +} + +static void policy_components_view_on_select_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data) +{ + GtkTreeView *tv = GTK_TREE_VIEW(user_data); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tv); + gtk_tree_selection_select_all(selection); +} + +static void policy_components_view_on_unselect_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data) +{ + GtkTreeView *tv = GTK_TREE_VIEW(user_data); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tv); + gtk_tree_selection_unselect_all(selection); +} + +static void policy_components_view_init_signals(struct polcomp_view *pv) +{ + g_signal_connect(pv->log_radio, "toggled", G_CALLBACK(policy_components_view_on_source_toggle), pv); + g_signal_connect(pv->policy_radio, "toggled", G_CALLBACK(policy_components_view_on_source_toggle), pv); + g_signal_connect(pv->both_radio, "toggled", G_CALLBACK(policy_components_view_on_source_toggle), pv); + g_signal_connect(pv->to_exc_button, "clicked", G_CALLBACK(policy_components_view_on_to_exc_click), pv); + g_signal_connect(pv->to_inc_button, "clicked", G_CALLBACK(policy_components_view_on_to_inc_click), pv); + g_signal_connect(pv->inc_select_button, "clicked", G_CALLBACK(policy_components_view_on_select_click), pv->inc_view); + g_signal_connect(pv->inc_unselect_button, "clicked", G_CALLBACK(policy_components_view_on_unselect_click), pv->inc_view); + g_signal_connect(pv->exc_select_button, "clicked", G_CALLBACK(policy_components_view_on_select_click), pv->exc_view); + g_signal_connect(pv->exc_unselect_button, "clicked", G_CALLBACK(policy_components_view_on_unselect_click), pv->exc_view); +} + +apol_vector_t *policy_components_view_run(toplevel_t * top, GtkWindow * parent __attribute__ ((unused)), const char *title, + apol_vector_t * log_items, apol_vector_t * policy_items, apol_vector_t * included) +{ + struct polcomp_view pv; + gint response; + + memset(&pv, 0, sizeof(pv)); + pv.top = top; + pv.xml = glade_xml_new(toplevel_get_glade_xml(top), "PolicyComponentListsWindow", NULL); + pv.log_items = log_items; + pv.policy_items = policy_items; + if (included == NULL) { + pv.included_items = apol_vector_create(free); + } else { + pv.included_items = apol_vector_create_from_vector(included, apol_str_strdup, NULL, free); + } + apol_vector_destroy(&included); + if (pv.included_items == NULL) { + toplevel_ERR(pv.top, "Error creating dialog: %s", strerror(errno)); + return NULL; + } + + policy_components_view_init_widgets(&pv); + policy_components_view_init_lists(&pv); + policy_components_view_init_signals(&pv); + gtk_window_set_title(GTK_WINDOW(pv.dialog), title); + do { + response = gtk_dialog_run(pv.dialog); + } while (response != GTK_RESPONSE_CLOSE); + + gtk_widget_destroy(GTK_WIDGET(pv.dialog)); + g_object_unref(pv.master_store); + g_object_unref(pv.inc_store); + g_object_unref(pv.exc_store); + apol_vector_destroy(&pv.both_items); + if (apol_vector_get_size(pv.included_items) == 0) { + apol_vector_destroy(&pv.included_items); + return NULL; + } + return pv.included_items; +} -- cgit