diff options
Diffstat (limited to 'sediff/remap_types_dialog.c')
-rw-r--r-- | sediff/remap_types_dialog.c | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/sediff/remap_types_dialog.c b/sediff/remap_types_dialog.c new file mode 100644 index 0000000..24c5b21 --- /dev/null +++ b/sediff/remap_types_dialog.c @@ -0,0 +1,564 @@ +/** + * @file + * Displays a dialog that allows users to explicitly remap/remap + * types from one policy to the other. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * @author Randy Wicks rwicks@tresys.com + * + * Copyright (C) 2005-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 <config.h> + +#include "remap_types_dialog.h" +#include "utilgui.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <apol/type-query.h> +#include <apol/util.h> +#include <glade/glade.h> +#include <poldiff/type_map.h> + +struct remap_types +{ + toplevel_t *top; + GladeXML *xml; + poldiff_t *diff; + /** main dialog widget for type remapps*/ + GtkDialog *dialog; + GtkTreeView *view; + GtkCheckButton *show_inferred; + /** drop-down combo boxes that allow user to add new remap */ + GtkComboBoxEntry *combo[SEDIFFX_POLICY_NUM]; + GtkCheckButton *show_unmapped_types; + GtkButton *add, *remove; + GtkListStore *remaps; + GtkTreeModelFilter *filter; + GtkTreeModelSort *sort; + /** non-zero if a type map was added or removed */ + int changed; +}; + +enum +{ + ORIG_NAME_COL = 0, MOD_NAME_COL, ORIG_HIGHLIGHT_VALUE_COL, MOD_HIGHLIGHT_VALUE_COL, ENTRY_COL, NUM_COLUMNS +}; + +static GtkTreeModelFilter *types_filter[SEDIFFX_POLICY_NUM] = { NULL, NULL }; +static GtkListStore *types[SEDIFFX_POLICY_NUM] = { NULL, NULL }; +static gboolean show_only_unmapped = TRUE; + +/** + * Go through all entries in the list store; for those that map the + * current entries for the combo boxes, highlight them. + */ +static void remap_types_highlight_entries(struct remap_types *rt) +{ + const gchar *orig_text = util_combo_box_get_active_text(GTK_COMBO_BOX(rt->combo[SEDIFFX_POLICY_ORIG])); + const gchar *mod_text = util_combo_box_get_active_text(GTK_COMBO_BOX(rt->combo[SEDIFFX_POLICY_MOD])); + int num_orig_matches = 0, num_mod_matches = 0; + gboolean iter_valid; + GtkTreeIter iter; + poldiff_type_remap_entry_t *entry; + apol_vector_t *v; + size_t idx; + iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(rt->remaps), &iter); + while (iter_valid) { + gtk_tree_model_get(GTK_TREE_MODEL(rt->remaps), &iter, ENTRY_COL, &entry, -1); + if (orig_text != NULL && strcmp(orig_text, "") != 0) { + v = poldiff_type_remap_entry_get_original_types(rt->diff, entry); + if (apol_vector_get_index(v, orig_text, apol_str_strcmp, NULL, &idx) == 0) { + gtk_list_store_set(rt->remaps, &iter, ORIG_HIGHLIGHT_VALUE_COL, PANGO_WEIGHT_BOLD, -1); + num_orig_matches++; + if (apol_vector_get_size(v) > 1) { + /* this will disallow the + * original type from being + * added again */ + num_orig_matches++; + } + } else { + gtk_list_store_set(rt->remaps, &iter, ORIG_HIGHLIGHT_VALUE_COL, PANGO_WEIGHT_NORMAL, -1); + } + apol_vector_destroy(&v); + } + if (mod_text != NULL && strcmp(mod_text, "") != 0) { + v = poldiff_type_remap_entry_get_modified_types(rt->diff, entry); + if (apol_vector_get_index(v, mod_text, apol_str_strcmp, NULL, &idx) == 0) { + gtk_list_store_set(rt->remaps, &iter, MOD_HIGHLIGHT_VALUE_COL, PANGO_WEIGHT_BOLD, -1); + num_mod_matches++; + if (apol_vector_get_size(v) > 1) { + /* this will disallow the + * modified type from being + * added again */ + num_mod_matches++; + } + } else { + gtk_list_store_set(rt->remaps, &iter, MOD_HIGHLIGHT_VALUE_COL, PANGO_WEIGHT_NORMAL, -1); + } + apol_vector_destroy(&v); + } + iter_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(rt->remaps), &iter); + } + gtk_widget_set_sensitive(GTK_WIDGET(rt->add), FALSE); + if (orig_text != NULL && strcmp(orig_text, "") != 0 && mod_text != NULL && strcmp(mod_text, "") != 0) { + /* enable the add button if and only if: number of + * orig and mod matches are both 0, or one side is 1 + * and the other is 0 */ + if ((num_orig_matches == 0 && num_mod_matches == 0) || + (num_orig_matches == 1 && num_mod_matches == 0) || (num_orig_matches == 0 && num_mod_matches == 1)) { + gtk_widget_set_sensitive(GTK_WIDGET(rt->add), TRUE); + } + } +} + +/** + * Populate the main tree model with all type remaps currently within + * the poldiff object. + */ +static void remap_types_update_view(struct remap_types *rt) +{ + apol_vector_t *entries = poldiff_type_remap_get_entries(rt->diff); + apol_vector_t *origs = NULL, *mods = NULL; + apol_vector_t *used_origs = NULL, *used_mods = NULL; + char *orig_string = NULL, *mod_string = NULL, *s, *t; + size_t i, j; + GtkTreeIter iter; + if ((used_origs = apol_vector_create(NULL)) == NULL || (used_mods = apol_vector_create(NULL)) == NULL) { + toplevel_ERR(rt->top, "%s", strerror(errno)); + goto cleanup; + } + gtk_list_store_clear(rt->remaps); + for (i = 0; i < apol_vector_get_size(entries); i++) { + poldiff_type_remap_entry_t *e = apol_vector_get_element(entries, i); + if ((origs = poldiff_type_remap_entry_get_original_types(rt->diff, e)) == NULL || + (mods = poldiff_type_remap_entry_get_modified_types(rt->diff, e)) == NULL || + (orig_string = apol_str_join(origs, ", ")) == NULL || (mod_string = apol_str_join(mods, ", ")) == NULL) { + toplevel_ERR(rt->top, "%s", strerror(errno)); + goto cleanup; + } + for (j = 0; j < apol_vector_get_size(origs); j++) { + s = apol_vector_get_element(origs, j); + if (apol_vector_append(used_origs, s) < 0) { + toplevel_ERR(rt->top, "%s", strerror(errno)); + goto cleanup; + } + } + for (j = 0; j < apol_vector_get_size(mods); j++) { + s = apol_vector_get_element(mods, j); + if (apol_vector_append(used_mods, s) < 0) { + toplevel_ERR(rt->top, "%s", strerror(errno)); + goto cleanup; + } + } + gtk_list_store_append(rt->remaps, &iter); + gtk_list_store_set(rt->remaps, &iter, ORIG_NAME_COL, orig_string, MOD_NAME_COL, mod_string, ENTRY_COL, e, -1); + apol_vector_destroy(&origs); + apol_vector_destroy(&mods); + free(orig_string); + free(mod_string); + orig_string = NULL; + mod_string = NULL; + } + + /* mark entries in the 'types' list store that are used. the + * algorithm works only because the types list store was + * sorted by remap_types_update(). */ + apol_vector_sort_uniquify(used_origs, apol_str_strcmp, NULL); + apol_vector_sort_uniquify(used_mods, apol_str_strcmp, NULL); + i = 0; + s = apol_vector_get_element(used_origs, i); + gboolean iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(types[SEDIFFX_POLICY_ORIG]), &iter); + while (iter_valid && s != NULL) { + gtk_tree_model_get(GTK_TREE_MODEL(types[SEDIFFX_POLICY_ORIG]), &iter, 0, &t, -1); + if (strcmp(s, t) == 0) { + gtk_list_store_set(types[SEDIFFX_POLICY_ORIG], &iter, 1, TRUE, -1); + i++; + s = apol_vector_get_element(used_origs, i); + } else { + gtk_list_store_set(types[SEDIFFX_POLICY_ORIG], &iter, 1, FALSE, -1); + } + iter_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(types[SEDIFFX_POLICY_ORIG]), &iter); + } + assert(i >= apol_vector_get_size(used_origs)); + + i = 0; + s = apol_vector_get_element(used_mods, i); + iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(types[SEDIFFX_POLICY_MOD]), &iter); + while (iter_valid && s != NULL) { + gtk_tree_model_get(GTK_TREE_MODEL(types[SEDIFFX_POLICY_MOD]), &iter, 0, &t, -1); + if (strcmp(s, t) == 0) { + gtk_list_store_set(types[SEDIFFX_POLICY_MOD], &iter, 1, TRUE, -1); + i++; + s = apol_vector_get_element(used_mods, i); + } else { + gtk_list_store_set(types[SEDIFFX_POLICY_MOD], &iter, 1, FALSE, -1); + } + iter_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(types[SEDIFFX_POLICY_MOD]), &iter); + } + assert(i >= apol_vector_get_size(used_mods)); + + remap_types_highlight_entries(rt); + gtk_tree_model_filter_refilter(types_filter[SEDIFFX_POLICY_ORIG]); + gtk_tree_model_filter_refilter(types_filter[SEDIFFX_POLICY_MOD]); + cleanup: + apol_vector_destroy(&used_origs); + apol_vector_destroy(&used_mods); + apol_vector_destroy(&origs); + apol_vector_destroy(&mods); + free(orig_string); + free(mod_string); +} + +static void remap_types_on_show_inferred_toggle(GtkToggleButton * toggle __attribute__ ((unused)), gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + gtk_tree_model_filter_refilter(rt->filter); +} + +static void remap_types_on_show_unmapped_types_toggle(GtkToggleButton * toggle, gpointer user_data __attribute__ ((unused))) +{ + show_only_unmapped = gtk_toggle_button_get_active(toggle); + gtk_tree_model_filter_refilter(types_filter[SEDIFFX_POLICY_ORIG]); + gtk_tree_model_filter_refilter(types_filter[SEDIFFX_POLICY_MOD]); +} + +static void remap_types_on_selection_change(GtkTreeSelection * selection, gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + gboolean sens = gtk_tree_selection_get_selected(selection, NULL, NULL); + gtk_widget_set_sensitive(GTK_WIDGET(rt->remove), sens); +} + +static void remap_types_on_combo_change(GtkComboBox * widget __attribute__ ((unused)), gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + remap_types_highlight_entries(rt); +} + +static void remap_types_on_add_click(GtkButton * button __attribute__ ((unused)), gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + apol_vector_t *orig = NULL, *mod = NULL; + apol_vector_t *old_orig = NULL, *old_mod = NULL; + const gchar *orig_type = util_combo_box_get_active_text(GTK_COMBO_BOX(rt->combo[SEDIFFX_POLICY_ORIG])); + const gchar *mod_type = util_combo_box_get_active_text(GTK_COMBO_BOX(rt->combo[SEDIFFX_POLICY_MOD])); + + if ((orig = apol_str_split(orig_type, " ")) == NULL || (mod = apol_str_split(mod_type, " ")) == NULL) { + toplevel_ERR(rt->top, "%s", strerror(errno)); + } + if (apol_vector_get_size(orig) > 1 && apol_vector_get_size(mod) > 1) { + toplevel_ERR(rt->top, "%s", "Remappings may be 1 to many or many to 1, but not many to many."); + goto cleanup; + } + + /* check all existing remap entries, to see if the user's + * entries should be appended to an existing entry */ + GtkTreeIter iter; + gboolean iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(rt->remaps), &iter); + poldiff_type_remap_entry_t *entry = NULL, *e; + /* remap_types_highlight_entries() should have already marked + * which of the existing entries match the user's inputs */ + while (iter_valid) { + gint orig_marked, mod_marked; + gtk_tree_model_get(GTK_TREE_MODEL(rt->remaps), &iter, ORIG_HIGHLIGHT_VALUE_COL, &orig_marked, + MOD_HIGHLIGHT_VALUE_COL, &mod_marked, ENTRY_COL, &e, -1); + assert(orig_marked != PANGO_WEIGHT_BOLD || mod_marked != PANGO_WEIGHT_BOLD); + if (orig_marked == PANGO_WEIGHT_BOLD) { + assert(entry == NULL); + entry = e; + } else if (mod_marked == PANGO_WEIGHT_BOLD) { + assert(entry == NULL); + entry = e; + } + iter_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(rt->remaps), &iter); + } + if (entry != NULL) { + size_t i; + char *s; + old_orig = poldiff_type_remap_entry_get_original_types(rt->diff, entry); + old_mod = poldiff_type_remap_entry_get_modified_types(rt->diff, entry); + assert(old_orig != NULL && old_mod != NULL); + for (i = 0; i < apol_vector_get_size(old_orig); i++) { + s = strdup(apol_vector_get_element(old_orig, i)); + if (apol_vector_append_unique(orig, s, apol_str_strcmp, NULL) > 0) { + free(s); + } + } + for (i = 0; i < apol_vector_get_size(old_mod); i++) { + s = strdup(apol_vector_get_element(old_mod, i)); + if (apol_vector_append_unique(mod, s, apol_str_strcmp, NULL) > 0) { + free(s); + } + } + poldiff_type_remap_entry_remove(rt->diff, entry); + } + + if (poldiff_type_remap_create(rt->diff, orig, mod) < 0) { + toplevel_ERR(rt->top, "%s", "This was not a valid type remap."); + goto cleanup; + } else { + remap_types_update_view(rt); + rt->changed = 1; + } + cleanup: + apol_vector_destroy(&orig); + apol_vector_destroy(&mod); + apol_vector_destroy(&old_orig); + apol_vector_destroy(&old_mod); +} + +static void remap_types_on_remove_click(GtkButton * button __attribute__ ((unused)), gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + GtkTreeSelection *selection = gtk_tree_view_get_selection(rt->view); + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { + poldiff_type_remap_entry_t *entry; + gtk_tree_model_get(GTK_TREE_MODEL(rt->sort), &iter, ENTRY_COL, &entry, -1); + poldiff_type_remap_entry_remove(rt->diff, entry); + remap_types_update_view(rt); + rt->changed = 1; + } +} + +static gint remap_types_sort_compare(GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data) +{ + gint column = GPOINTER_TO_INT(user_data); + char *s, *t; + gtk_tree_model_get(model, a, column, &s, -1); + gtk_tree_model_get(model, b, column, &t, -1); + /* these next two conditionals are needed because while the remap + * list store is being built, a row will temporarily have empty + * strings */ + if (s == NULL) { + s = ""; + } + if (t == NULL) { + t = ""; + } + return strcmp(s, t); +} + +static gboolean remap_types_filter_visible(GtkTreeModel * model, GtkTreeIter * iter, gpointer user_data) +{ + struct remap_types *rt = (struct remap_types *)user_data; + poldiff_type_remap_entry_t *entry; + gtk_tree_model_get(model, iter, ENTRY_COL, &entry, -1); + if (poldiff_type_remap_entry_get_is_inferred(entry)) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rt->show_inferred))) { + return TRUE; + } + return FALSE; + } else { + /* explicit maps are always shown */ + return TRUE; + } +} + +static void remap_types_init_widgets(struct remap_types *rt) +{ + GtkTreeSelection *selection; + GtkCellRenderer *orig_renderer, *mod_renderer; + GtkTreeViewColumn *column; + + rt->dialog = GTK_DIALOG(glade_xml_get_widget(rt->xml, "remap_types")); + assert(rt->dialog != NULL); + gtk_window_set_transient_for(GTK_WINDOW(rt->dialog), toplevel_get_window(rt->top)); + rt->view = GTK_TREE_VIEW(glade_xml_get_widget(rt->xml, "remap_types treeview")); + rt->show_inferred = GTK_CHECK_BUTTON(glade_xml_get_widget(rt->xml, "remap_types inferred checkbutton")); + rt->combo[SEDIFFX_POLICY_ORIG] = GTK_COMBO_BOX_ENTRY(glade_xml_get_widget(rt->xml, "remap_types orig combo")); + rt->combo[SEDIFFX_POLICY_MOD] = GTK_COMBO_BOX_ENTRY(glade_xml_get_widget(rt->xml, "remap_types mod combo")); + rt->show_unmapped_types = GTK_CHECK_BUTTON(glade_xml_get_widget(rt->xml, "remap_types only unmapped checkbutton")); + assert(rt->view != NULL && rt->show_inferred && rt->combo[SEDIFFX_POLICY_ORIG] != NULL + && rt->combo[SEDIFFX_POLICY_MOD] != NULL && rt->show_unmapped_types != NULL); + g_signal_connect(rt->show_inferred, "toggled", G_CALLBACK(remap_types_on_show_inferred_toggle), rt); + g_signal_connect(rt->show_unmapped_types, "toggled", G_CALLBACK(remap_types_on_show_unmapped_types_toggle), rt); + show_only_unmapped = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rt->show_unmapped_types)); + + rt->add = GTK_BUTTON(glade_xml_get_widget(rt->xml, "remap_types add button")); + rt->remove = GTK_BUTTON(glade_xml_get_widget(rt->xml, "remap_types remove button")); + assert(rt->add != NULL && rt->remove != NULL); + g_signal_connect(rt->add, "clicked", G_CALLBACK(remap_types_on_add_click), rt); + g_signal_connect(rt->remove, "clicked", G_CALLBACK(remap_types_on_remove_click), rt); + + rt->remaps = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER); + rt->filter = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(GTK_TREE_MODEL(rt->remaps), NULL)); + gtk_tree_model_filter_set_visible_func(rt->filter, remap_types_filter_visible, rt, NULL); + rt->sort = GTK_TREE_MODEL_SORT(gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(rt->filter))); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(rt->sort), ORIG_NAME_COL, remap_types_sort_compare, + GINT_TO_POINTER(ORIG_NAME_COL), NULL); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(rt->sort), MOD_NAME_COL, remap_types_sort_compare, + GINT_TO_POINTER(MOD_NAME_COL), NULL); + gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(rt->sort), remap_types_sort_compare, + GINT_TO_POINTER(ORIG_NAME_COL), NULL); + gtk_tree_view_set_model(rt->view, GTK_TREE_MODEL(rt->sort)); + + selection = gtk_tree_view_get_selection(rt->view); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); + g_signal_connect(selection, "changed", G_CALLBACK(remap_types_on_selection_change), rt); + + orig_renderer = gtk_cell_renderer_text_new(); + mod_renderer = gtk_cell_renderer_text_new(); + g_object_set(orig_renderer, "weight", PANGO_WEIGHT_BOLD, NULL); + g_object_set(mod_renderer, "weight", PANGO_WEIGHT_BOLD, NULL); + column = gtk_tree_view_column_new_with_attributes("Original Policy", orig_renderer, "text", ORIG_NAME_COL, "weight", + ORIG_HIGHLIGHT_VALUE_COL, NULL); + gtk_tree_view_column_set_expand(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, ORIG_NAME_COL); + gtk_tree_view_column_set_sort_indicator(column, TRUE); + gtk_tree_view_append_column(GTK_TREE_VIEW(rt->view), column); + gtk_tree_view_column_clicked(column); + + column = gtk_tree_view_column_new_with_attributes("Modified Policy", mod_renderer, "text", MOD_NAME_COL, "weight", + MOD_HIGHLIGHT_VALUE_COL, NULL); + gtk_tree_view_column_set_expand(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, MOD_NAME_COL); + gtk_tree_view_column_set_sort_indicator(column, TRUE); + gtk_tree_view_append_column(GTK_TREE_VIEW(rt->view), column); +} + +static gboolean remap_types_types_filter_visible(GtkTreeModel * model, GtkTreeIter * iter, gpointer user_data); + +/** + * Set up the combo boxes to show only types unique to that policy. + * (The lists of types were calculated by remap_types_update().) + */ +static void remap_types_init_combos(struct remap_types *rt) +{ + sediffx_policy_e i; + for (i = SEDIFFX_POLICY_ORIG; i < SEDIFFX_POLICY_NUM; i++) { + gtk_combo_box_set_model(GTK_COMBO_BOX(rt->combo[i]), GTK_TREE_MODEL(types_filter[i])); + gtk_combo_box_entry_set_text_column(rt->combo[i], 0); + g_signal_connect(rt->combo[i], "changed", G_CALLBACK(remap_types_on_combo_change), rt); + } +} + +int remap_types_run(toplevel_t * top) +{ + struct remap_types rt; + gint response; + static gboolean prev_show_inferred = FALSE; + static gboolean prev_show_unmapped = TRUE; + + memset(&rt, 0, sizeof(rt)); + rt.top = top; + rt.xml = glade_xml_new(toplevel_get_glade_xml(rt.top), "remap_types", NULL); + rt.diff = toplevel_get_poldiff(rt.top); + + remap_types_init_widgets(&rt); + remap_types_init_combos(&rt); + remap_types_update_view(&rt); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rt.show_inferred), prev_show_inferred); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rt.show_unmapped_types), prev_show_unmapped); + + response = gtk_dialog_run(rt.dialog); + + prev_show_inferred = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rt.show_inferred)); + prev_show_unmapped = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rt.show_unmapped_types)); + gtk_widget_destroy(GTK_WIDGET(rt.dialog)); + g_object_unref(rt.sort); + g_object_unref(rt.filter); + g_object_unref(rt.remaps); + return rt.changed; +} + +static gboolean remap_types_types_filter_visible(GtkTreeModel * model, GtkTreeIter * iter, gpointer user_data + __attribute__ ((unused))) +{ + gboolean in_use; + if (!show_only_unmapped) { + return TRUE; + } + /* otherwise show types that are not being used */ + gtk_tree_model_get(model, iter, 1, &in_use, -1); + return !in_use; +} + +/** + * Alphabetize a list of qpol_type_t, base upon their names. + */ +static int remap_types_qpol_type_cmp(const void *a, const void *b, void *data) +{ + const qpol_type_t *x = a; + const qpol_type_t *y = b; + qpol_policy_t *q = (qpol_policy_t *) data; + const char *s, *t; + qpol_type_get_name(q, x, &s); + qpol_type_get_name(q, y, &t); + return strcmp(s, t); +} + +int remap_types_update(apol_policy_t * orig_policy, apol_policy_t * mod_policy) +{ + qpol_policy_t *oq = apol_policy_get_qpol(orig_policy); + qpol_policy_t *mq = apol_policy_get_qpol(mod_policy); + apol_vector_t *v = NULL; + sediffx_policy_e which; + size_t i; + const qpol_type_t *t; + const char *type_name; + GtkTreeIter iter; + int error = 0, retval = -1; + + for (which = SEDIFFX_POLICY_ORIG; which < SEDIFFX_POLICY_NUM; which++) { + if (types[which] == NULL) { + types[which] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN); + types_filter[which] = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(GTK_TREE_MODEL(types[which]), NULL)); + gtk_tree_model_filter_set_visible_func(types_filter[which], remap_types_types_filter_visible, NULL, NULL); + } else { + gtk_list_store_clear(types[which]); + } + } + + if (apol_type_get_by_query(orig_policy, NULL, &v) < 0) { + error = errno; + goto cleanup; + } + apol_vector_sort(v, remap_types_qpol_type_cmp, oq); + for (i = 0; i < apol_vector_get_size(v); i++) { + t = apol_vector_get_element(v, i); + qpol_type_get_name(oq, t, &type_name); + gtk_list_store_append(types[SEDIFFX_POLICY_ORIG], &iter); + gtk_list_store_set(types[SEDIFFX_POLICY_ORIG], &iter, 0, type_name, -1); + } + apol_vector_destroy(&v); + + if (apol_type_get_by_query(mod_policy, NULL, &v) < 0) { + error = errno; + goto cleanup; + } + apol_vector_sort(v, remap_types_qpol_type_cmp, mq); + for (i = 0; i < apol_vector_get_size(v); i++) { + t = apol_vector_get_element(v, i); + qpol_type_get_name(mq, t, &type_name); + gtk_list_store_append(types[SEDIFFX_POLICY_MOD], &iter); + gtk_list_store_set(types[SEDIFFX_POLICY_MOD], &iter, 0, type_name, -1); + } + retval = 0; + cleanup: + apol_vector_destroy(&v); + if (retval != 0) { + errno = error; + return retval; + } + return retval; +} |