# Copyright (C) 2013 Red Hat
# see file 'COPYING' for use and warranty information
#
# selinux gui is a tool for the examining and modifying SELinux policy
#
#    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., 59 Temple Place, Suite 330, Boston, MA
#                                        02111-1307  USA
#
#    author: Ryan Hallisey rhallisey@redhat.com
#    author: Dan Walsh dwalsh@redhat.com
#    author: Miroslav Grepl mgrepl@redhat.com
#
#

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
from sepolicy.sedbus import SELinuxDBus
import sys
import sepolicy
import selinux
from selinux import DISABLED, PERMISSIVE, ENFORCING
import sepolicy.network
import sepolicy.manpage
import dbus
import os
import re
import unicodedata

PROGNAME = "selinux-python"
try:
    import gettext
    kwargs = {}
    if sys.version_info < (3,):
        kwargs['unicode'] = True
    t = gettext.translation(PROGNAME,
                    localedir="/usr/share/locale",
                    **kwargs,
                    fallback=True)
    _ = t.gettext
except:
    try:
        import builtins
        builtins.__dict__['_'] = str
    except ImportError:
        import __builtin__
        __builtin__.__dict__['_'] = unicode

reverse_file_type_str = {}
for f in sepolicy.file_type_str:
    reverse_file_type_str[sepolicy.file_type_str[f]] = f

enabled = [_("No"), _("Yes")]
action = [_("Disable"), _("Enable")]


def cmp(a, b):
    if a is None and b is None:
        return 0
    if a is None:
        return -1
    if b is None:
        return 1
    return (a > b) - (a < b)

import sysconfig
ADVANCED_LABEL = (_("Advanced >>"), _("Advanced <<"))
ADVANCED_SEARCH_LABEL = (_("Advanced Search >>"), _("Advanced Search <<"))
OUTBOUND_PAGE = 0
INBOUND_PAGE = 1

TRANSITIONS_FROM_PAGE = 0
TRANSITIONS_TO_PAGE = 1
TRANSITIONS_FILE_PAGE = 2

EXE_PAGE = 0
WRITABLE_PAGE = 1
APP_PAGE = 2

BOOLEANS_PAGE = 0
FILES_PAGE = 1
NETWORK_PAGE = 2
TRANSITIONS_PAGE = 3
LOGIN_PAGE = 4
USER_PAGE = 5
LOCKDOWN_PAGE = 6
SYSTEM_PAGE = 7
FILE_EQUIV_PAGE = 8
START_PAGE = 9

keys = ["boolean", "fcontext", "fcontext-equiv", "port", "login", "user", "module", "node", "interface"]

DISABLED_TEXT = _("""<small>
To change from Disabled to Enforcing mode
- Change the system mode from Disabled to Permissive
- Reboot, so that the system can relabel
- Once the system is working as planned
  * Change the system mode to Enforcing</small>
""")


class SELinuxGui():

    def __init__(self, app=None, test=False):
        self.finish_init = False
        self.advanced_init = True
        self.opage = START_PAGE
        self.dbus = SELinuxDBus()
        try:
            customized = self.dbus.customized()
        except dbus.exceptions.DBusException as e:
            print(e)
            self.quit()

        self.init_cur()
        self.application = app
        self.filter_txt = ""
        builder = Gtk.Builder()  # BUILDER OBJ
        self.code_path = sysconfig.get_path('purelib', vars={'base': "/usr"}) + "/sepolicy/"
        glade_file = self.code_path + "sepolicy.glade"
        builder.add_from_file(glade_file)
        self.outer_notebook = builder.get_object("outer_notebook")
        self.window = builder.get_object("SELinux_window")
        self.main_selection_popover = builder.get_object("Main_selection_menu")
        self.main_advanced_label = builder.get_object("main_advanced_label")
        self.applications_selection_button = builder.get_object("applications_selection_button")
        self.revert_button = builder.get_object("Revert_button")
        self.busy_cursor = Gdk.Cursor(Gdk.CursorType.WATCH)
        self.ready_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
        self.initialtype = selinux.selinux_getpolicytype()[1]
        self.current_popup = None
        self.import_export = None
        self.clear_entry = True
        self.files_add = False
        self.network_add = False
        self.mislabeled_files = False

        self.all_domains = []
        self.installed_list = []
        self.previously_modified = {}

        # file dialog
        self.file_dialog = builder.get_object("add_path_dialog")
        # Error check ***************************************
        self.error_check_window = builder.get_object("error_check_window")
        self.error_check_label = builder.get_object("error_check_label")
        self.invalid_entry = False
        # Advanced search window ****************************
        self.advanced_search_window = builder.get_object("advanced_search_window")
        self.advanced_search_filter = builder.get_object("advanced_filter")
        self.advanced_search_filter.set_visible_func(self.filter_the_data)
        self.advanced_search_sort = builder.get_object("advanced_sort")

        self.advanced_filter_entry = builder.get_object("advanced_filter_entry")
        self.advanced_search_treeview = builder.get_object("advanced_search_treeview")
        self.advanced_search = False

        # Login Items **************************************
        self.login_label = builder.get_object("Login_label")
        self.login_seuser_combobox = builder.get_object("login_seuser_combobox")
        self.login_seuser_combolist = builder.get_object("login_seuser_liststore")
        self.login_name_entry = builder.get_object("login_name_entry")
        self.login_mls_label = builder.get_object("login_mls_label")
        self.login_mls_entry = builder.get_object("login_mls_entry")
        self.login_radio_button = builder.get_object("Login_button")
        self.login_treeview = builder.get_object("login_treeview")
        self.login_liststore = builder.get_object("login_liststore")
        self.login_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.login_filter = builder.get_object("login_filter")
        self.login_filter.set_visible_func(self.filter_the_data)
        self.login_popup_window = builder.get_object("login_popup_window")
        self.login_delete_liststore = builder.get_object("login_delete_liststore")
        self.login_delete_window = builder.get_object("login_delete_window")

        # Users Items **************************************
        self.user_popup_window = builder.get_object("user_popup_window")
        self.user_radio_button = builder.get_object("User_button")
        self.user_liststore = builder.get_object("user_liststore")
        self.user_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.user_filter = builder.get_object("user_filter")
        self.user_filter.set_visible_func(self.filter_the_data)
        self.user_treeview = builder.get_object("user_treeview")
        self.user_roles_combobox = builder.get_object("user_roles_combobox")
        self.user_roles_combolist = builder.get_object("user_roles_liststore")
        self.user_label = builder.get_object("User_label")
        self.user_name_entry = builder.get_object("user_name_entry")
        self.user_mls_label = builder.get_object("user_mls_label")
        self.user_mls_level_entry = builder.get_object("user_mls_level_entry")
        self.user_mls_entry = builder.get_object("user_mls_entry")
        self.user_combobox = builder.get_object("selinux_user_combobox")
        self.user_delete_liststore = builder.get_object("user_delete_liststore")
        self.user_delete_window = builder.get_object("user_delete_window")

        # File Equiv Items **************************************
        self.file_equiv_label = builder.get_object("file_equiv_label")
        self.file_equiv_source_entry = builder.get_object("file_equiv_source_entry")
        self.file_equiv_dest_entry = builder.get_object("file_equiv_dest_entry")
        self.file_equiv_radio_button = builder.get_object("file_equiv_button")
        self.file_equiv_treeview = builder.get_object("file_equiv_treeview")
        self.file_equiv_liststore = builder.get_object("file_equiv_liststore")
        self.file_equiv_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.file_equiv_popup_window = builder.get_object("file_equiv_popup_window")
        self.file_equiv_treefilter = builder.get_object("file_equiv_filter")
        self.file_equiv_treefilter.set_visible_func(self.filter_the_data)
        self.file_equiv_delete_liststore = builder.get_object("file_equiv_delete_liststore")
        self.file_equiv_delete_window = builder.get_object("file_equiv_delete_window")

        # System Items **************************************
        self.app_system_button = builder.get_object("app_system_button")
        self.system_radio_button = builder.get_object("System_button")
        self.lockdown_radio_button = builder.get_object("Lockdown_button")
        self.systems_box = builder.get_object("Systems_box")
        self.relabel_button = builder.get_object("Relabel_button")
        self.relabel_button_no = builder.get_object("Relabel_button_no")
        self.advanced_system = builder.get_object("advanced_system")
        self.outer_notebook_frame = builder.get_object("outer_notebook_frame")
        self.system_policy_label = builder.get_object("system_policy_type_label")
        # Browse Items **************************************
        self.select_button_browse = builder.get_object("select_button_browse")
        self.cancel_button_browse = builder.get_object("cancel_button_browse")
        # More types window items ***************************
        self.moreTypes_window_files = builder.get_object("moreTypes_window_files")
        self.more_types_files_liststore = builder.get_object("more_types_file_liststore")
        self.moreTypes_treeview = builder.get_object("moreTypes_treeview_files")
        # System policy type ********************************
        self.system_policy_type_liststore = builder.get_object("system_policy_type_liststore")
        self.system_policy_type_combobox = builder.get_object("system_policy_type_combobox")
        self.policy_list = []
        if self.populate_system_policy() < 2:
            self.advanced_system.set_visible(False)
            self.system_policy_label.set_visible(False)
            self.system_policy_type_combobox.set_visible(False)

        self.enforcing_button_default = builder.get_object("Enforcing_button_default")
        self.permissive_button_default = builder.get_object("Permissive_button_default")
        self.disabled_button_default = builder.get_object("Disabled_button_default")
        self.initialize_system_default_mode()

        # Lockdown Window *********************************
        self.enable_unconfined_button = builder.get_object("enable_unconfined")
        self.disable_unconfined_button = builder.get_object("disable_unconfined")
        self.enable_permissive_button = builder.get_object("enable_permissive")
        self.disable_permissive_button = builder.get_object("disable_permissive")
        self.enable_ptrace_button = builder.get_object("enable_ptrace")
        self.disable_ptrace_button = builder.get_object("disable_ptrace")

        # Help Window *********************************
        self.help_window = builder.get_object("help_window")
        self.help_text = builder.get_object("help_textv")
        self.info_text = builder.get_object("info_text")
        self.help_image = builder.get_object("help_image")
        self.forward_button = builder.get_object("forward_button")
        self.back_button = builder.get_object("back_button")
        # Update menu items *********************************
        self.update_window = builder.get_object("update_window")
        self.update_treeview = builder.get_object("update_treeview")
        self.update_treestore = builder.get_object("Update_treestore")
        self.apply_button = builder.get_object("apply_button")
        self.update_button = builder.get_object("Update_button")
        # Add button objects ********************************
        self.add_button = builder.get_object("Add_button")
        self.delete_button = builder.get_object("Delete_button")

        self.files_path_entry = builder.get_object("files_path_entry")
        self.network_ports_entry = builder.get_object("network_ports_entry")
        self.files_popup_window = builder.get_object("files_popup_window")
        self.network_popup_window = builder.get_object("network_popup_window")

        self.popup_network_label = builder.get_object("Network_label")
        self.popup_files_label = builder.get_object("files_label")

        self.recursive_path_toggle = builder.get_object("make_path_recursive")
        self.files_type_combolist = builder.get_object("files_type_combo_store")
        self.files_class_combolist = builder.get_object("files_class_combo_store")
        self.files_type_combobox = builder.get_object("files_type_combobox")
        self.files_class_combobox = builder.get_object("files_class_combobox")
        self.files_mls_label = builder.get_object("files_mls_label")
        self.files_mls_entry = builder.get_object("files_mls_entry")
        self.advanced_text_files = builder.get_object("Advanced_text_files")
        self.files_cancel_button = builder.get_object("cancel_delete_files")

        self.network_tcp_button = builder.get_object("tcp_button")
        self.network_udp_button = builder.get_object("udp_button")
        self.network_port_type_combolist = builder.get_object("network_type_combo_store")
        self.network_port_type_combobox = builder.get_object("network_type_combobox")
        self.network_mls_label = builder.get_object("network_mls_label")
        self.network_mls_entry = builder.get_object("network_mls_entry")
        self.advanced_text_network = builder.get_object("Advanced_text_network")
        self.network_cancel_button = builder.get_object("cancel_network_delete")

        # Add button objects ********************************

        # Modify items **************************************
        self.show_mislabeled_files_only = builder.get_object("Show_mislabeled_files")
        self.mislabeled_files_label = builder.get_object("mislabeled_files_label")
        self.warning_files = builder.get_object("warning_files")
        self.modify_button = builder.get_object("Modify_button")
        self.modify_button.set_sensitive(False)
        # Modify items **************************************

        # Fix label *****************************************
        self.fix_label_window = builder.get_object("fix_label_window")
        self.fixlabel_label = builder.get_object("fixlabel_label")
        self.fix_label_cancel = builder.get_object("fix_label_cancel")
        # Fix label *****************************************

        # Delete items **************************************
        self.files_delete_window = builder.get_object("files_delete_window")
        self.files_delete_treeview = builder.get_object("files_delete_treeview")
        self.files_delete_liststore = builder.get_object("files_delete_liststore")
        self.network_delete_window = builder.get_object("network_delete_window")
        self.network_delete_treeview = builder.get_object("network_delete_treeview")
        self.network_delete_liststore = builder.get_object("network_delete_liststore")
        # Delete items **************************************

        # Progress bar **************************************
        self.progress_bar = builder.get_object("progress_bar")
        # Progress bar **************************************

        # executable_files items ****************************
        self.executable_files_treeview = builder.get_object("Executable_files_treeview")                  # Get the executable files tree view
        self.executable_files_filter = builder.get_object("executable_files_filter")
        self.executable_files_filter.set_visible_func(self.filter_the_data)
        self.executable_files_tab = builder.get_object("Executable_files_tab")
        self.executable_files_tab_tooltip_txt = self.executable_files_tab.get_tooltip_text()
        self.executable_files_liststore = builder.get_object("executable_files_treestore")
        self.executable_files_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)

        self.files_radio_button = builder.get_object("files_button")
        self.files_button_tooltip_txt = self.files_radio_button.get_tooltip_text()
        # executable_files items ****************************

        # writable files items ******************************
        self.writable_files_treeview = builder.get_object("Writable_files_treeview")           # Get the Writable files tree view
        self.writable_files_liststore = builder.get_object("writable_files_treestore")         # Contains the tree with File Path, SELinux File Label, Class
        self.writable_files_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.writable_files_filter = builder.get_object("writable_files_filter")
        self.writable_files_filter.set_visible_func(self.filter_the_data)
        self.writable_files_tab = builder.get_object("Writable_files_tab")
        self.writable_files_tab_tooltip_txt = self.writable_files_tab.get_tooltip_text()
        # writable files items ******************************

        # Application File Types ****************************
        self.application_files_treeview = builder.get_object("Application_files_treeview")                    # Get the Application files tree view
        self.application_files_filter = builder.get_object("application_files_filter")         # Contains the tree with File Path, Description, Class
        self.application_files_filter.set_visible_func(self.filter_the_data)
        self.application_files_tab = builder.get_object("Application_files_tab")
        self.application_files_tab_tooltip_txt = self.writable_files_tab.get_tooltip_text()
        self.application_files_liststore = builder.get_object("application_files_treestore")
        self.application_files_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.application_files_tab = builder.get_object("Application_files_tab")
        self.application_files_tab_tooltip_txt = self.application_files_tab.get_tooltip_text()
        # Application File Type *****************************

        # network items *************************************
        self.network_radio_button = builder.get_object("network_button")
        self.network_button_tooltip_txt = self.network_radio_button.get_tooltip_text()

        self.network_out_treeview = builder.get_object("outbound_treeview")
        self.network_out_liststore = builder.get_object("network_out_liststore")
        self.network_out_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.network_out_filter = builder.get_object("network_out_filter")
        self.network_out_filter.set_visible_func(self.filter_the_data)
        self.network_out_tab = builder.get_object("network_out_tab")
        self.network_out_tab_tooltip_txt = self.network_out_tab.get_tooltip_text()

        self.network_in_treeview = builder.get_object("inbound_treeview")
        self.network_in_liststore = builder.get_object("network_in_liststore")
        self.network_in_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.network_in_filter = builder.get_object("network_in_filter")
        self.network_in_filter.set_visible_func(self.filter_the_data)
        self.network_in_tab = builder.get_object("network_in_tab")
        self.network_in_tab_tooltip_txt = self.network_in_tab.get_tooltip_text()
        # network items *************************************

        # boolean items ************************************
        self.boolean_treeview = builder.get_object("Boolean_treeview")         # Get the booleans tree list
        self.boolean_liststore = builder.get_object("boolean_liststore")
        self.boolean_liststore.set_sort_column_id(2, Gtk.SortType.ASCENDING)
        self.boolean_filter = builder.get_object("boolean_filter")
        self.boolean_filter.set_visible_func(self.filter_the_data)

        self.boolean_more_detail_window = builder.get_object("booleans_more_detail_window")
        self.boolean_more_detail_treeview = builder.get_object("booleans_more_detail_treeview")
        self.boolean_more_detail_tree_data_set = builder.get_object("booleans_more_detail_liststore")
        self.boolean_radio_button = builder.get_object("Booleans_button")
        self.active_button = self.boolean_radio_button
        self.boolean_button_tooltip_txt = self.boolean_radio_button.get_tooltip_text()
        # boolean items ************************************

        # transitions items ************************************
        self.transitions_into_treeview = builder.get_object("transitions_into_treeview")         # Get the transitions tree list Enabled, source, Executable File
        self.transitions_into_liststore = builder.get_object("transitions_into_liststore")   # Contains the tree with
        self.transitions_into_liststore.set_sort_column_id(1, Gtk.SortType.ASCENDING)
        self.transitions_into_filter = builder.get_object("transitions_into_filter")
        self.transitions_into_filter.set_visible_func(self.filter_the_data)
        self.transitions_into_tab = builder.get_object("Transitions_into_tab")
        self.transitions_into_tab_tooltip_txt = self.transitions_into_tab.get_tooltip_text()

        self.transitions_radio_button = builder.get_object("Transitions_button")
        self.transitions_button_tooltip_txt = self.transitions_radio_button.get_tooltip_text()

        self.transitions_from_treeview = builder.get_object("transitions_from_treeview")         # Get the transitions tree list
        self.transitions_from_treestore = builder.get_object("transitions_from_treestore")       # Contains the tree with Enabled, Executable File Type, Transtype
        self.transitions_from_treestore.set_sort_column_id(2, Gtk.SortType.ASCENDING)
        self.transitions_from_filter = builder.get_object("transitions_from_filter")
        self.transitions_from_filter.set_visible_func(self.filter_the_data)
        self.transitions_from_tab = builder.get_object("Transitions_from_tab")
        self.transitions_from_tab_tooltip_txt = self.transitions_from_tab.get_tooltip_text()

        self.transitions_file_treeview = builder.get_object("file_transitions_treeview")         # Get the transitions tree list
        self.transitions_file_liststore = builder.get_object("file_transitions_liststore")       # Contains the tree with Enabled, Executable File Type, Transtype
        self.transitions_file_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
        self.transitions_file_filter = builder.get_object("file_transitions_filter")
        self.transitions_file_filter.set_visible_func(self.filter_the_data)
        self.transitions_file_tab = builder.get_object("file_transitions")
        self.transitions_file_tab_tooltip_txt = self.transitions_from_tab.get_tooltip_text()
        # transitions items ************************************

        # Combobox and Entry items **************************
        self.combobox_menu = builder.get_object("combobox_org")                    # This is the combobox box object, aka the arrow next to the entry text bar
        self.application_liststore = builder.get_object("application_liststore")
        self.completion_entry = builder.get_object("completion_entry")  # self.combobox_menu.get_child()
        self.entrycompletion_obj = builder.get_object("entrycompletion_obj")
        #self.entrycompletion_obj = Gtk.EntryCompletion()
        self.entrycompletion_obj.set_minimum_key_length(0)
        self.entrycompletion_obj.set_text_column(0)
        self.entrycompletion_obj.set_match_func(self.match_func, None)
        self.completion_entry.set_completion(self.entrycompletion_obj)
        self.completion_entry.set_icon_from_stock(0, Gtk.STOCK_FIND)
        # Combobox and Entry items **************************

        # Modify buttons ************************************
        self.show_modified_only = builder.get_object("Show_modified_only_toggle")
        # Modify button *************************************

        # status bar *****************************************
        self.current_status_label = builder.get_object("Enforcing_label")
        self.current_status_enforcing = builder.get_object("Enforcing_button")
        self.current_status_permissive = builder.get_object("Permissive_button")
        self.status_bar = builder.get_object("status_bar")
        self.context_id = self.status_bar.get_context_id("SELinux status")

        # filters *********************************************
        self.filter_entry = builder.get_object("filter_entry")
        self.filter_box = builder.get_object("filter_box")
        self.add_modify_delete_box = builder.get_object("add_modify_delete_box")
        # Get_model() sets the tree model filter to be the parent of the tree model (tree model has all the data in it)

        # Toggle button ****************************************
        self.cell = builder.get_object("activate")
        self.del_cell_files = builder.get_object("files_toggle_delete")
        self.del_cell_files.connect("toggled", self.on_toggle_update, self.files_delete_liststore)
        self.del_cell_files_equiv = builder.get_object("file_equiv_toggle_delete1")
        self.del_cell_files_equiv.connect("toggled", self.on_toggle_update, self.file_equiv_delete_liststore)
        self.del_cell_user = builder.get_object("user_toggle_delete")
        self.del_cell_user.connect("toggled", self.on_toggle_update, self.user_delete_liststore)
        self.del_cell_login = builder.get_object("login_toggle_delete")
        self.del_cell_login.connect("toggled", self.on_toggle_update, self.login_delete_liststore)
        self.del_cell_network = builder.get_object("network_toggle_delete")
        self.del_cell_network.connect("toggled", self.on_toggle_update, self.network_delete_liststore)
        self.update_cell = builder.get_object("toggle_update")
        # Notebook items ***************************************
        self.outer_notebook = builder.get_object("outer_notebook")
        self.inner_notebook_files = builder.get_object("files_inner_notebook")
        self.inner_notebook_network = builder.get_object("network_inner_notebook")
        self.inner_notebook_transitions = builder.get_object("transitions_inner_notebook")
        # logind gui ***************************************
        loading_gui = builder.get_object("loading_gui")

        self.update_cell.connect("toggled", self.on_toggle_update, self.update_treestore)
        self.all_entries = []

        # Need to connect button on code because the tree view model is a treeviewsort
        self.cell.connect("toggled", self.on_toggle, self.boolean_liststore)

        self.loading = 1
        path = None
        if test:
            self.all_domains = ["httpd_t", "abrt_t"]
            if app and app not in self.all_domains:
                self.all_domains.append(app)
        else:
            self.all_domains = sepolicy.get_all_domains()
        self.all_domains.sort(key=str.lower)

        if app and app not in self.all_domains:
            self.error(_("%s is not a valid domain") % app)
            self.quit()

        loading_gui.show()
        length = len(self.all_domains)

        entrypoint_dict = sepolicy.get_init_entrypoints_str()
        for domain in self.all_domains:
            # After the user selects a path in the drop down menu call
            # get_init_entrypoint_target(entrypoint) to get the transtype
            # which will give you the application
            self.combo_box_add(domain, domain)
            self.percentage = float(float(self.loading) / float(length))
            self.progress_bar.set_fraction(self.percentage)
            self.progress_bar.set_pulse_step(self.percentage)
            self.idle_func()

            for entrypoint in entrypoint_dict.get(domain, []):
                path = sepolicy.find_entrypoint_path(entrypoint)
                if path:
                    self.combo_box_add(path, domain)
                    self.installed_list.append(path)

            self.loading += 1
        loading_gui.hide()
        self.entrycompletion_obj.set_model(self.application_liststore)
        self.advanced_search_treeview.set_model(self.advanced_search_sort)

        dic = {
            "on_combo_button_clicked": self.open_combo_menu,
            "on_disable_ptrace_toggled": self.on_disable_ptrace,
            "on_entrycompletion_obj_match_selected": self.set_application_label,
            "on_filter_changed": self.get_filter_data,
            "on_save_changes_file_equiv_clicked": self.update_to_file_equiv,
            "on_save_changes_login_clicked": self.update_to_login,
            "on_save_changes_user_clicked": self.update_to_user,
            "on_save_changes_files_clicked": self.update_to_files,
            "on_save_changes_network_clicked": self.update_to_network,
            "on_Advanced_text_files_button_press_event": self.reveal_advanced,
            "item_in_tree_selected": self.cursor_changed,
            "on_Application_file_types_treeview_configure_event": self.resize_wrap,
            "on_save_delete_clicked": self.on_save_delete_clicked,
            "on_moreTypes_treeview_files_row_activated": self.populate_type_combo,
            "on_retry_button_files_clicked": self.invalid_entry_retry,
            "on_make_path_recursive_toggled": self.recursive_path,
            "on_files_path_entry_button_press_event": self.highlight_entry_text,
            "on_files_path_entry_changed": self.autofill_add_files_entry,
            "on_select_type_files_clicked": self.select_type_more,
            "on_choose_file": self.on_browse_select,
            "on_Enforcing_button_toggled": self.set_enforce,
            "on_confirmation_close": self.confirmation_close,
            "on_column_clicked": self.column_clicked,
            "on_tab_switch": self.clear_filters,

            "on_file_equiv_button_clicked": self.show_file_equiv_page,
            "on_app/system_button_clicked": self.system_interface,
            "on_app/users_button_clicked": self.users_interface,
            "on_show_advanced_search_window": self.on_show_advanced_search_window,

            "on_Show_mislabeled_files_toggled": self.show_mislabeled_files,
            "on_Browse_button_files_clicked": self.browse_for_files,
            "on_cancel_popup_clicked": self.close_popup,
            "on_treeview_cursor_changed": self.cursor_changed,
            "on_login_seuser_combobox_changed": self.login_seuser_combobox_change,
            "on_user_roles_combobox_changed": self.user_roles_combobox_change,

            "on_cancel_button_browse_clicked": self.close_config_window,
            "on_apply_button_clicked": self.apply_changes_button_press,
            "on_Revert_button_clicked": self.update_or_revert_changes,
            "on_Update_button_clicked": self.update_or_revert_changes,
            "on_advanced_filter_entry_changed": self.get_advanced_filter_data,
            "on_advanced_search_treeview_row_activated": self.advanced_item_selected,
            "on_Select_advanced_search_clicked": self.advanced_item_button_push,
            "on_info_button_button_press_event": self.on_help_button,
            "on_back_button_clicked": self.on_help_back_clicked,
            "on_forward_button_clicked": self.on_help_forward_clicked,
            "on_Boolean_treeview_columns_changed": self.resize_columns,
            "on_completion_entry_changed": self.application_selected,
            "on_Add_button_clicked": self.add_button_clicked,
            "on_Delete_button_clicked": self.delete_button_clicked,
            "on_Modify_button_clicked": self.modify_button_clicked,
            "on_Show_modified_only_toggled": self.on_show_modified_only,
            "on_cancel_button_config_clicked": self.close_config_window,
            "on_Import_button_clicked": self.import_config_show,
            "on_Export_button_clicked": self.export_config_show,
            "on_enable_unconfined_toggled": self.unconfined_toggle,
            "on_enable_permissive_toggled": self.permissive_toggle,
            "on_system_policy_type_combobox_changed": self.change_default_policy,
            "on_Enforcing_button_default_toggled": self.change_default_mode,
            "on_Permissive_button_default_toggled": self.change_default_mode,
            "on_Disabled_button_default_toggled": self.change_default_mode,

            "on_Relabel_button_toggled_cb": self.relabel_on_reboot,
            "on_advanced_system_button_press_event": self.reveal_advanced_system,
            "on_files_type_combobox_changed": self.show_more_types,
            "on_filter_row_changed": self.filter_the_data,
            "on_button_toggled": self.tab_change,
            "gtk_main_quit": self.closewindow
        }

        self.previously_modified_initialize(customized)
        builder.connect_signals(dic)
        self.window.show()                # Show the gui to the screen
        GLib.timeout_add_seconds(5, self.selinux_status)
        self.selinux_status()
        self.lockdown_inited = False
        self.add_modify_delete_box.hide()
        self.filter_box.hide()
        if self.status == DISABLED:
            self.show_system_page()
        else:
            if self.application:
                self.applications_selection_button.set_label(self.application)
                self.completion_entry.set_text(self.application)
                self.show_applications_page()
                self.tab_change()
            else:
                self.clearbuttons()
                self.outer_notebook.set_current_page(START_PAGE)

        self.reinit()
        self.finish_init = True
        Gtk.main()

    def init_cur(self):
        self.cur_dict = {}
        for k in keys:
            self.cur_dict[k] = {}

    def remove_cur(self, ctr):
        i = 0
        for k in self.cur_dict:
            for j in self.cur_dict[k]:
                if i == ctr:
                    del self.cur_dict[k][j]
                    return
                i += 1

    def selinux_status(self):
        try:
            self.status = selinux.security_getenforce()
        except OSError:
            self.status = DISABLED
        if self.status == DISABLED:
            self.current_status_label.set_sensitive(False)
            self.current_status_enforcing.set_sensitive(False)
            self.current_status_permissive.set_sensitive(False)
            self.enforcing_button_default.set_sensitive(False)
            self.status_bar.push(self.context_id, _("System Status: Disabled"))
            self.info_text.set_label(DISABLED_TEXT)
        else:
            self.set_enforce_text(self.status)
        if os.path.exists('/.autorelabel'):
            self.relabel_button.set_active(True)
        else:
            self.relabel_button_no.set_active(True)

        policytype = selinux.selinux_getpolicytype()[1]

        mode = selinux.selinux_getenforcemode()[1]
        if mode == ENFORCING:
            self.enforcing_button_default.set_active(True)
        if mode == PERMISSIVE:
            self.permissive_button_default.set_active(True)
        if mode == DISABLED:
            self.disabled_button_default.set_active(True)

        return True

    def lockdown_init(self):
        if self.lockdown_inited:
            return
        self.wait_mouse()
        self.lockdown_inited = True
        self.disable_ptrace_button.set_active(selinux.security_get_boolean_active("deny_ptrace"))
        self.module_dict = {}
        for m in self.dbus.semodule_list().split("\n"):
            mod = m.split()
            if len(mod) < 3:
                continue
            self.module_dict[mod[1]] = { "priority": mod[0], "Disabled" : (len(mod) > 3) }

        self.enable_unconfined_button.set_active(not self.module_dict["unconfined"]["Disabled"])
        self.enable_permissive_button.set_active(not self.module_dict["permissivedomains"]["Disabled"])
        self.ready_mouse()

    def column_clicked(self, treeview, treepath, treecol, *args):
        iter = self.get_selected_iter()
        if not iter:
            return

        if self.opage == BOOLEANS_PAGE:
            if treecol.get_name() == "more_detail_col":
                self.display_more_detail(self.window, treepath)

        if self.opage == FILES_PAGE:
            visible = self.liststore.get_value(iter, 3)
            # If visible is true then fix mislabeled will be visible
            if treecol.get_name() == "restorecon_col" and visible:
                self.fix_mislabeled(self.liststore.get_value(iter, 0))

        if self.opage == TRANSITIONS_PAGE:
            bool_name = self.liststore.get_value(iter, 1)
            if bool_name:
                self.boolean_radio_button.clicked()
                self.filter_entry.set_text(bool_name)

    def idle_func(self):
        while Gtk.events_pending():
            Gtk.main_iteration()

    def match_func(self, completion, key_string, iter, func_data):
        try:
            if self.application_liststore.get_value(iter, 0).find(key_string) != -1:
                return True
            return False
        except AttributeError:
            pass

    def help_show_page(self):
        self.back_button.set_sensitive(self.help_page != 0)
        self.forward_button.set_sensitive(self.help_page < (len(self.help_list) - 1))
        try:
            fd = open("%shelp/%s.txt" % (self.code_path, self.help_list[self.help_page]), "r")
            buf = fd.read()
            fd.close()
        except IOError:
            buf = ""
        help_text = self.help_text.get_buffer()
        help_text.set_text(buf % {"APP": self.application})
        self.help_text.set_buffer(help_text)
        self.help_image.set_from_file("%shelp/%s.png" % (self.code_path, self.help_list[self.help_page]))
        self.show_popup(self.help_window)

    def on_help_back_clicked(self, *args):
        self.help_page -= 1
        self.help_show_page()

    def on_help_forward_clicked(self, *args):
        self.help_page += 1
        self.help_show_page()

    def on_help_button(self, *args):
        self.help_page = 0
        self.help_list = []
        if self.opage == START_PAGE:
            self.help_window.set_title(_("Help: Start Page"))
            self.help_list = ["start"]

        if self.opage == BOOLEANS_PAGE:
            self.help_window.set_title(_("Help: Booleans Page"))
            self.help_list = ["booleans", "booleans_toggled", "booleans_more", "booleans_more_show"]

        if self.opage == FILES_PAGE:
            ipage = self.inner_notebook_files.get_current_page()
            if ipage == EXE_PAGE:
                self.help_window.set_title(_("Help: Executable Files Page"))
                self.help_list = ["files_exec"]
            if ipage == WRITABLE_PAGE:
                self.help_window.set_title(_("Help: Writable Files Page"))
                self.help_list = ["files_write"]
            if ipage == APP_PAGE:
                self.help_window.set_title(_("Help: Application Types Page"))
                self.help_list = ["files_app"]
        if self.opage == NETWORK_PAGE:
            ipage = self.inner_notebook_network.get_current_page()
            if ipage == OUTBOUND_PAGE:
                self.help_window.set_title(_("Help: Outbound Network Connections Page"))
                self.help_list = ["ports_outbound"]
            if ipage == INBOUND_PAGE:
                self.help_window.set_title(_("Help: Inbound Network Connections Page"))
                self.help_list = ["ports_inbound"]

        if self.opage == TRANSITIONS_PAGE:
            ipage = self.inner_notebook_transitions.get_current_page()
            if ipage == TRANSITIONS_FROM_PAGE:
                self.help_window.set_title(_("Help: Transition from application Page"))
                self.help_list = ["transition_from", "transition_from_boolean", "transition_from_boolean_1", "transition_from_boolean_2"]
            if ipage == TRANSITIONS_TO_PAGE:
                self.help_window.set_title(_("Help: Transition into application Page"))
                self.help_list = ["transition_to"]
            if ipage == TRANSITIONS_FILE_PAGE:
                self.help_window.set_title(_("Help: Transition application file Page"))
                self.help_list = ["transition_file"]

        if self.opage == SYSTEM_PAGE:
            self.help_window.set_title(_("Help: Systems Page"))
            self.help_list = ["system", "system_boot_mode", "system_current_mode", "system_export", "system_policy_type", "system_relabel"]

        if self.opage == LOCKDOWN_PAGE:
            self.help_window.set_title(_("Help: Lockdown Page"))
            self.help_list = ["lockdown", "lockdown_unconfined", "lockdown_permissive", "lockdown_ptrace"]

        if self.opage == LOGIN_PAGE:
            self.help_window.set_title(_("Help: Login Page"))
            self.help_list = ["login", "login_default"]

        if self.opage == USER_PAGE:
            self.help_window.set_title(_("Help: SELinux User Page"))
            self.help_list = ["users"]

        if self.opage == FILE_EQUIV_PAGE:
            self.help_window.set_title(_("Help: File Equivalence Page"))
            self.help_list = ["file_equiv"]
        return self.help_show_page()

    def open_combo_menu(self, *args):
        self.main_selection_popover.set_relative_to(self.applications_selection_button)
        self.main_selection_popover.popup()

    def set_application_label(self, *args):
        self.set_application_label = True

    def resize_wrap(self, *args):
        print(args)

    def initialize_system_default_mode(self):
        self.enforce_mode = selinux.selinux_getenforcemode()[1]
        if self.enforce_mode == ENFORCING:
            self.enforce_button = self.enforcing_button_default
        if self.enforce_mode == PERMISSIVE:
            self.enforce_button = self.permissive_button_default
        if self.enforce_mode == DISABLED:
            self.enforce_button = self.disabled_button_default

    def populate_system_policy(self):
        types = next(os.walk(selinux.selinux_path(), topdown=True))[1]
        types.sort()
        ctr = 0
        for item in types:
            iter = self.system_policy_type_liststore.append()
            self.system_policy_type_liststore.set_value(iter, 0, item)
            if item == self.initialtype:
                self.system_policy_type_combobox.set_active(ctr)
                self.typeHistory = ctr
            ctr += 1
        return ctr

    def filter_the_data(self, list, iter, *args):
        # When there is no txt in the box show all items in the tree
        if self.filter_txt == "":
            return True
        try:
            for x in range(0, list.get_n_columns()):
                try:
                    val = list.get_value(iter, x)
                    if val is True or val is False or val is None:
                        continue
                    # Returns true if filter_txt exists within the val
                    if val.find(self.filter_txt) != -1 or val.lower().find(self.filter_txt) != -1:
                        return True
                except (AttributeError, TypeError):
                    pass
        except:  # ValueError:
            pass
        return False

    def net_update(self, app, netd, protocol, direction, model):
        for k in netd.keys():
            for t, ports in netd[k]:
                pkey = (",".join(ports), protocol)
                if pkey in self.cur_dict["port"]:
                    if self.cur_dict["port"][pkey]["action"] == "-d":
                        continue
                    if t != self.cur_dict["port"][pkey]["type"]:
                        continue
                self.network_initial_data_insert(model, ", ".join(ports), t, protocol)

    def file_equiv_initialize(self):
        self.wait_mouse()
        edict = sepolicy.get_file_equiv()
        self.file_equiv_liststore.clear()
        for f in edict:
            iter = self.file_equiv_liststore.append()
            if edict[f]["modify"]:
                name = self.markup(f)
                equiv = self.markup(edict[f]["equiv"])
            else:
                name = f
                equiv = edict[f]["equiv"]

            self.file_equiv_liststore.set_value(iter, 0, name)
            self.file_equiv_liststore.set_value(iter, 1, equiv)
            self.file_equiv_liststore.set_value(iter, 2, edict[f]["modify"])
        self.ready_mouse()

    def user_initialize(self):
        self.wait_mouse()
        self.user_liststore.clear()
        for u in sepolicy.get_selinux_users():
            iter = self.user_liststore.append()
            self.user_liststore.set_value(iter, 0, str(u["name"]))
            roles = u["roles"]
            if "object_r" in roles:
                roles.remove("object_r")
            self.user_liststore.set_value(iter, 1, ", ".join(roles))
            self.user_liststore.set_value(iter, 2, u.get("level", ""))
            self.user_liststore.set_value(iter, 3, u.get("range", ""))
            self.user_liststore.set_value(iter, 4, True)
        self.ready_mouse()

    def login_initialize(self):
        self.wait_mouse()
        self.login_liststore.clear()
        for u in sepolicy.get_login_mappings():
            iter = self.login_liststore.append()
            self.login_liststore.set_value(iter, 0, u["name"])
            self.login_liststore.set_value(iter, 1, u["seuser"])
            self.login_liststore.set_value(iter, 2, u["mls"])
            self.login_liststore.set_value(iter, 3, True)
        self.ready_mouse()

    def network_initialize(self, app):
        netd = sepolicy.network.get_network_connect(app, "tcp", "name_connect", check_bools=True)
        self.net_update(app, netd, "tcp", OUTBOUND_PAGE, self.network_out_liststore)
        netd = sepolicy.network.get_network_connect(app, "tcp", "name_bind", check_bools=True)
        self.net_update(app, netd, "tcp", INBOUND_PAGE, self.network_in_liststore)
        netd = sepolicy.network.get_network_connect(app, "udp", "name_bind", check_bools=True)
        self.net_update(app, netd, "udp", INBOUND_PAGE, self.network_in_liststore)

    def network_initial_data_insert(self, model, ports, portType, protocol):
        iter = model.append()
        model.set_value(iter, 0, ports)
        model.set_value(iter, 1, protocol)
        model.set_value(iter, 2, portType)
        model.set_value(iter, 4, True)

    def combo_set_active_text(self, combobox, val):
        ctr = 0
        liststore = combobox.get_model()
        for i in liststore:
            if i[0] == val:
                combobox.set_active(ctr)
                return
            ctr += 1

        niter = liststore.get_iter(ctr - 1)
        if liststore.get_value(niter, 0) == _("More..."):
            iter = liststore.insert_before(niter)
            ctr = ctr - 1
        else:
            iter = liststore.append()
        liststore.set_value(iter, 0, val)
        combobox.set_active(ctr)

    def combo_get_active_text(self, combobox):
        liststore = combobox.get_model()
        index = combobox.get_active()
        if index < 0:
            return None
        iter = liststore.get_iter(index)
        return liststore.get_value(iter, 0)

    def combo_box_add(self, val, val1):
        if val is None:
            return
        iter = self.application_liststore.append()
        self.application_liststore.set_value(iter, 0, val)
        self.application_liststore.set_value(iter, 1, val1)

    def select_type_more(self, *args):
        app = self.moreTypes_treeview.get_selection()
        iter = app.get_selected()[1]
        if iter is None:
            return
        app = self.more_types_files_liststore.get_value(iter, 0)
        self.combo_set_active_text(self.files_type_combobox, app)
        self.closewindow(self.moreTypes_window_files)

    def advanced_item_button_push(self, *args):
        row = self.advanced_search_treeview.get_selection()
        model, iter = row.get_selected()
        iter = model.convert_iter_to_child_iter(iter)
        iter = self.advanced_search_filter.convert_iter_to_child_iter(iter)
        app = self.application_liststore.get_value(iter, 1)
        if app is None:
            return
        self.advanced_filter_entry.set_text('')
        self.advanced_search_window.hide()
        self.reveal_advanced(self.main_advanced_label)
        self.completion_entry.set_text(app)

    def advanced_item_selected(self, treeview, path, *args):
        iter = self.advanced_search_filter.get_iter(path)
        iter = self.advanced_search_filter.convert_iter_to_child_iter(iter)
        app = self.application_liststore.get_value(iter, 1)
        self.advanced_filter_entry.set_text('')
        self.advanced_search_window.hide()
        self.reveal_advanced(self.main_advanced_label)
        self.completion_entry.set_text(app)
        self.application_selected()

    def find_application(self, app):
        if app and len(app) > 0:
            for items in self.application_liststore:
                if app == items[0]:
                    return True
        return False

    def application_selected(self, *args):
        self.show_mislabeled_files_only.set_visible(False)
        self.mislabeled_files_label.set_visible(False)
        self.warning_files.set_visible(False)
        self.filter_entry.set_text('')

        app = self.completion_entry.get_text()
        if not self.find_application(app):
            return
        self.show_applications_page()
        self.add_button.set_sensitive(True)
        self.delete_button.set_sensitive(True)
        # Clear the tree to prepare for a new selection otherwise
        self.executable_files_liststore.clear()
        # data will pile up every time the user selects a new item from the drop down menu
        self.network_in_liststore.clear()
        self.network_out_liststore.clear()
        self.boolean_liststore.clear()
        self.transitions_into_liststore.clear()
        self.transitions_from_treestore.clear()
        self.application_files_liststore.clear()
        self.writable_files_liststore.clear()
        self.transitions_file_liststore.clear()

        try:
            if app[0] == '/':
                app = sepolicy.get_init_transtype(app)
                if not app:
                    return
                self.application = app
        except IndexError:
            pass

        self.wait_mouse()
        self.previously_modified_initialize(self.dbus.customized())
        self.reinit()
        self.boolean_initialize(app)
        self.mislabeled_files = False
        self.executable_files_initialize(app)
        self.network_initialize(app)
        self.writable_files_initialize(app)
        self.transitions_into_initialize(app)
        self.transitions_from_initialize(app)
        self.application_files_initialize(app)
        self.transitions_files_initialize(app)

        self.executable_files_tab.set_tooltip_text(_("File path used to enter the '%s' domain.") % app)
        self.writable_files_tab.set_tooltip_text(_("Files to which the '%s' domain can write.") % app)
        self.network_out_tab.set_tooltip_text(_("Network Ports to which the '%s' is allowed to connect.") % app)
        self.network_in_tab.set_tooltip_text(_("Network Ports to which the '%s' is allowed to listen.") % app)
        self.application_files_tab.set_tooltip_text(_("File Types defined for the '%s'.") % app)
        self.boolean_radio_button.set_tooltip_text(_("Display boolean information that can be used to modify the policy for the '%s'.") % app)
        self.files_radio_button.set_tooltip_text(_("Display file type information that can be used by the '%s'.") % app)
        self.network_radio_button.set_tooltip_text(_("Display network ports to which the '%s' can connect or listen to.") % app)
        self.transitions_into_tab.set_label(_("Application Transitions Into '%s'") % app)
        self.transitions_from_tab.set_label(_("Application Transitions From '%s'") % app)
        self.transitions_file_tab.set_label(_("File Transitions From '%s'") % app)
        self.transitions_into_tab.set_tooltip_text(_("Executables which will transition to '%s', when executing selected domains entrypoint.") % app)
        self.transitions_from_tab.set_tooltip_text(_("Executables which will transition to a different domain, when '%s' executes them.") % app)
        self.transitions_file_tab.set_tooltip_text(_("Files by '%s' with transitions to a different label.") % app)
        self.transitions_radio_button.set_tooltip_text(_("Display applications that can transition into or out of the '%s'.") % app)

        self.application = app
        self.applications_selection_button.set_label(self.application)
        self.ready_mouse()

    def reinit(self):
        sepolicy.reinit()
        self.fcdict = sepolicy.get_fcdict()
        self.local_file_paths = sepolicy.get_local_file_paths()

    def previously_modified_initialize(self, buf):
        self.cust_dict = {}
        for i in buf.split("\n"):
            rec = i.split()
            if len(rec) == 0:
                continue
            if rec[1] == "-D":
                continue
            if rec[0] not in self.cust_dict:
                self.cust_dict[rec[0]] = {}
            if rec[0] == "boolean":
                self.cust_dict["boolean"][rec[-1]] = {"active": rec[2] == "-1"}
            if rec[0] == "login":
                self.cust_dict["login"][rec[-1]] = {"seuser": rec[3], "range": rec[5]}
            if rec[0] == "interface":
                self.cust_dict["interface"][rec[-1]] = {"type": rec[3]}
            if rec[0] == "user":
                self.cust_dict["user"][rec[-1]] = {"level": "s0", "range": rec[3], "role": rec[5]}
            if rec[0] == "port":
                self.cust_dict["port"][(rec[-1], rec[-2])] = {"type": rec[3]}
            if rec[0] == "node":
                self.cust_dict["node"][rec[-1]] = {"mask": rec[3], "protocol": rec[5], "type": rec[7]}
            if rec[0] == "fcontext":
                if rec[2] == "-e":
                    if "fcontext-equiv" not in self.cust_dict:
                        self.cust_dict["fcontext-equiv"] = {}
                    self.cust_dict["fcontext-equiv"][(rec[-1])] = {"equiv": rec[3]}
                else:
                    self.cust_dict["fcontext"][(rec[-1], rec[3])] = {"type": rec[5]}
            if rec[0] == "module":
                self.cust_dict["module"][rec[-1]] = {"enabled": rec[2] != "-d"}

        if "module" not in self.cust_dict:
            return
        for semodule, button in [("unconfined", self.disable_unconfined_button), ("permissivedomains", self.disable_permissive_button)]:
            if semodule in self.cust_dict["module"]:
                button.set_active(self.cust_dict["module"][semodule]["enabled"])

        for i in keys:
            if i not in self.cust_dict:
                self.cust_dict.update({i: {}})

    def executable_files_initialize(self, application):
        self.entrypoints = sepolicy.get_entrypoints(application)
        for exe in self.entrypoints.keys():
            if len(self.entrypoints[exe]) == 0:
                continue
            file_class = self.entrypoints[exe][1]
            for path in self.entrypoints[exe][0]:
                if (path, file_class) in self.cur_dict["fcontext"]:
                    if self.cur_dict["fcontext"][(path, file_class)]["action"] == "-d":
                        continue
                    if exe != self.cur_dict["fcontext"][(path, file_class)]["type"]:
                        continue
                self.files_initial_data_insert(self.executable_files_liststore, path, exe, file_class)

    def mislabeled(self, path):
        try:
            con = selinux.matchpathcon(path, 0)[1]
            cur = selinux.getfilecon(path)[1]
            return con != cur
        except OSError:
            return False

    def set_mislabeled(self, tree, path, iter, niter):
        if not self.mislabeled(path):
            return
        con = selinux.matchpathcon(path, 0)[1]
        cur = selinux.getfilecon(path)[1]
        self.mislabeled_files = True
        # Set visibility of label
        tree.set_value(niter, 3, True)
        # Has a mislabel
        tree.set_value(iter, 4, True)
        tree.set_value(niter, 4, True)
        tree.set_value(iter, 5, con.split(":")[2])
        tree.set_value(iter, 6, cur.split(":")[2])

    def writable_files_initialize(self, application):
        # Traversing the dictionary data struct
        self.writable_files = sepolicy.get_writable_files(application)
        for write in self.writable_files.keys():
            if len(self.writable_files[write]) < 2:
                self.files_initial_data_insert(self.writable_files_liststore, None, write, _("all files"))
                continue
            file_class = self.writable_files[write][1]
            for path in self.writable_files[write][0]:
                if (path, file_class) in self.cur_dict["fcontext"]:
                    if self.cur_dict["fcontext"][(path, file_class)]["action"] == "-d":
                        continue
                    if write != self.cur_dict["fcontext"][(path, file_class)]["type"]:
                        continue
                self.files_initial_data_insert(self.writable_files_liststore, path, write, file_class)

    def files_initial_data_insert(self, liststore, path, selinux_label, file_class):
        iter = liststore.append(None)
        if path is None:
            path = _("MISSING FILE PATH")
            modify = False
        else:
            modify = (path, file_class) in self.local_file_paths
            for p in sepolicy.find_file(path):
                niter = liststore.append(iter)
                liststore.set_value(niter, 0, p)
                self.set_mislabeled(liststore, p, iter, niter)
            if modify:
                path = self.markup(path)
                file_class = self.markup(selinux_label)
                file_class = self.markup(file_class)
        liststore.set_value(iter, 0, path)
        liststore.set_value(iter, 1, selinux_label)
        liststore.set_value(iter, 2, file_class)
        liststore.set_value(iter, 7, modify)

    def markup(self, f):
        return "<b>%s</b>" % f

    def unmarkup(self, f):
        if f:
            return re.sub("</b>$", "", re.sub("^<b>", "", f))
        return None

    def application_files_initialize(self, application):
        self.file_types = sepolicy.get_file_types(application)
        for app in self.file_types.keys():
            if len(self.file_types[app]) == 0:
                continue
            file_class = self.file_types[app][1]
            for path in self.file_types[app][0]:
                desc = sepolicy.get_description(app, markup=self.markup)
                if (path, file_class) in self.cur_dict["fcontext"]:
                    if self.cur_dict["fcontext"][(path, file_class)]["action"] == "-d":
                        continue
                    if app != self.cur_dict["fcontext"][(path, file_class)]["type"]:
                        continue
                self.files_initial_data_insert(self.application_files_liststore, path, desc, file_class)

    def modified(self):
        i = 0
        for k in self.cur_dict:
            if len(self.cur_dict[k]) > 0:
                return True
        return False

    def boolean_initialize(self, application):
        for blist in sepolicy.get_bools(application):
            for b, active in blist:
                if b in self.cur_dict["boolean"]:
                    active = self.cur_dict["boolean"][b]['active']
                desc = sepolicy.boolean_desc(b)
                self.boolean_initial_data_insert(b, desc, active)

    def boolean_initial_data_insert(self, val, desc, active):
        # Insert data from data source into tree
        iter = self.boolean_liststore.append()
        self.boolean_liststore.set_value(iter, 0, active)
        self.boolean_liststore.set_value(iter, 1, desc)
        self.boolean_liststore.set_value(iter, 2, val)
        self.boolean_liststore.set_value(iter, 3, _('More...'))

    def transitions_into_initialize(self, application):
        for x in sepolicy.get_transitions_into(application):
            active = None
            executable = None
            source = None
            if "boolean" in x:
                active = x["boolean"]
            if "target" in x:
                executable = x["target"]
            if "source" in x:
                source = x["source"]
            self.transitions_into_initial_data_insert(active, executable, source)

    def transitions_into_initial_data_insert(self, active, executable, source):
        iter = self.transitions_into_liststore.append()
        if active != None:
            self.transitions_into_liststore.set_value(iter, 0, enabled[active[0][1]])         # active[0][1] is either T or F (enabled is all the way at the top)
        else:
            self.transitions_into_liststore.set_value(iter, 0, "Default")

        self.transitions_into_liststore.set_value(iter, 2, executable)
        self.transitions_into_liststore.set_value(iter, 1, source)

    def transitions_from_initialize(self, application):
        for x in sepolicy.get_transitions(application):
            active = None
            executable = None
            transtype = None
            if "boolean" in x:
                active = x["boolean"]
            if "target" in x:
                executable_type = x["target"]
            if "transtype" in x:
                transtype = x["transtype"]
            self.transitions_from_initial_data_insert(active, executable_type, transtype)
            try:
                for executable in self.fcdict[executable_type]["regex"]:
                    self.transitions_from_initial_data_insert(active, executable, transtype)
            except KeyError:
                pass

    def transitions_from_initial_data_insert(self, active, executable, transtype):
        iter = self.transitions_from_treestore.append(None)
        if active == None:
            self.transitions_from_treestore.set_value(iter, 0, "Default")
            self.transitions_from_treestore.set_value(iter, 5, False)
        else:
            niter = self.transitions_from_treestore.append(iter)
            # active[0][1] is either T or F (enabled is all the way at the top)
            self.transitions_from_treestore.set_value(iter, 0, enabled[active[0][1]])
            markup = ('<span foreground="blue"><u>','</u></span>')
            if active[0][1]:
                self.transitions_from_treestore.set_value(niter, 2, (_("To disable this transition, go to the %sBoolean section%s.") % markup))
            else:
                self.transitions_from_treestore.set_value(niter, 2, (_("To enable this transition, go to the %sBoolean section%s.") % markup))

            # active[0][0] is the Bool Name
            self.transitions_from_treestore.set_value(niter, 1, active[0][0])
            self.transitions_from_treestore.set_value(niter, 5, True)

        self.transitions_from_treestore.set_value(iter, 2, executable)
        self.transitions_from_treestore.set_value(iter, 3, transtype)

    def transitions_files_initialize(self, application):
        for i in sepolicy.get_file_transitions(application):
            if 'filename' in i:
                filename = i['filename']
            else:
                filename = None
            self.transitions_files_initial_data_insert(i['target'], i['class'], i['transtype'], filename)

    def transitions_files_initial_data_insert(self, path, tclass, dest, name):
        iter = self.transitions_file_liststore.append()
        self.transitions_file_liststore.set_value(iter, 0, path)
        self.transitions_file_liststore.set_value(iter, 1, tclass)
        self.transitions_file_liststore.set_value(iter, 2, dest)
        if name == None:
            name = '*'
        self.transitions_file_liststore.set_value(iter, 3, name)

    def tab_change(self, *args):
        self.clear_filters()
        self.treeview = None
        self.treesort = None
        self.treefilter = None
        self.liststore = None
        self.modify_button.set_sensitive(False)
        self.add_modify_delete_box.hide()
        self.show_modified_only.set_visible(False)
        self.show_mislabeled_files_only.set_visible(False)
        self.mislabeled_files_label.set_visible(False)
        self.warning_files.set_visible(False)

        if self.boolean_radio_button.get_active():
            self.outer_notebook.set_current_page(BOOLEANS_PAGE)
            self.treeview = self.boolean_treeview
            self.show_modified_only.set_visible(True)

        if self.files_radio_button.get_active():
            self.show_popup(self.add_modify_delete_box)
            self.show_modified_only.set_visible(True)
            self.show_mislabeled_files_only.set_visible(self.mislabeled_files)
            self.mislabeled_files_label.set_visible(self.mislabeled_files)
            self.warning_files.set_visible(self.mislabeled_files)
            self.outer_notebook.set_current_page(FILES_PAGE)
            if args[0] == self.inner_notebook_files:
                ipage = args[2]
            else:
                ipage = self.inner_notebook_files.get_current_page()
            if ipage == EXE_PAGE:
                self.treeview = self.executable_files_treeview
                category = _("executable")
            elif ipage == WRITABLE_PAGE:
                self.treeview = self.writable_files_treeview
                category = _("writable")
            elif ipage == APP_PAGE:
                self.treeview = self.application_files_treeview
                category = _("application")
            self.add_button.set_tooltip_text(_("Add new %(TYPE)s file path for '%(DOMAIN)s' domains.") % {"TYPE": category, "DOMAIN": self.application})
            self.delete_button.set_tooltip_text(_("Delete %(TYPE)s file paths for '%(DOMAIN)s' domain.") % {"TYPE": category, "DOMAIN": self.application})
            self.modify_button.set_tooltip_text(_("Modify %(TYPE)s file path for '%(DOMAIN)s' domain. Only bolded items in the list can be selected, this indicates they were modified previously.") % {"TYPE": category, "DOMAIN": self.application})

        if self.network_radio_button.get_active():
            self.add_modify_delete_box.show()
            self.show_modified_only.set_visible(True)
            self.outer_notebook.set_current_page(NETWORK_PAGE)
            if args[0] == self.inner_notebook_network:
                ipage = args[2]
            else:
                ipage = self.inner_notebook_network.get_current_page()
            if ipage == OUTBOUND_PAGE:
                self.treeview = self.network_out_treeview
                category = _("connect")
            if ipage == INBOUND_PAGE:
                self.treeview = self.network_in_treeview
                category = _("listen for inbound connections")

            self.add_button.set_tooltip_text(_("Add new port definition to which the '%(APP)s' domain is allowed to %(PERM)s.") % {"APP": self.application, "PERM": category})
            self.delete_button.set_tooltip_text(_("Delete modified port definitions to which the '%(APP)s' domain is allowed to %(PERM)s.") % {"APP": self.application, "PERM": category})
            self.modify_button.set_tooltip_text(_("Modify port definitions to which the '%(APP)s' domain is allowed to %(PERM)s.") % {"APP": self.application, "PERM": category})

        if self.transitions_radio_button.get_active():
            self.outer_notebook.set_current_page(TRANSITIONS_PAGE)
            if args[0] == self.inner_notebook_transitions:
                ipage = args[2]
            else:
                ipage = self.inner_notebook_transitions.get_current_page()
            if ipage == TRANSITIONS_FROM_PAGE:
                self.treeview = self.transitions_from_treeview
            if ipage == TRANSITIONS_TO_PAGE:
                self.treeview = self.transitions_into_treeview
            if ipage == TRANSITIONS_FILE_PAGE:
                self.treeview = self.transitions_file_treeview

        if self.system_radio_button.get_active():
            self.outer_notebook.set_current_page(SYSTEM_PAGE)
            self.filter_box.hide()

        if self.lockdown_radio_button.get_active():
            self.lockdown_init()
            self.outer_notebook.set_current_page(LOCKDOWN_PAGE)
            self.filter_box.hide()

        if self.user_radio_button.get_active():
            self.outer_notebook.set_current_page(USER_PAGE)
            self.add_modify_delete_box.show()
            self.show_modified_only.set_visible(True)
            self.treeview = self.user_treeview
            self.add_button.set_tooltip_text(_("Add new SELinux User/Role definition."))
            self.delete_button.set_tooltip_text(_("Delete modified SELinux User/Role definitions."))
            self.modify_button.set_tooltip_text(_("Modify selected modified SELinux User/Role definitions."))

        if self.login_radio_button.get_active():
            self.outer_notebook.set_current_page(LOGIN_PAGE)
            self.add_modify_delete_box.show()
            self.show_modified_only.set_visible(True)
            self.treeview = self.login_treeview
            self.add_button.set_tooltip_text(_("Add new Login Mapping definition."))
            self.delete_button.set_tooltip_text(_("Delete modified Login Mapping definitions."))
            self.modify_button.set_tooltip_text(_("Modify selected modified Login Mapping definitions."))

        if self.file_equiv_radio_button.get_active():
            self.outer_notebook.set_current_page(FILE_EQUIV_PAGE)
            self.add_modify_delete_box.show()
            self.show_modified_only.set_visible(True)
            self.treeview = self.file_equiv_treeview
            self.add_button.set_tooltip_text(_("Add new File Equivalence definition."))
            self.delete_button.set_tooltip_text(_("Delete modified File Equivalence definitions."))
            self.modify_button.set_tooltip_text(_("Modify selected modified File Equivalence definitions. Only bolded items in the list can be selected, this indicates they were modified previously."))

        self.opage = self.outer_notebook.get_current_page()
        if self.treeview:
            self.filter_box.show()
            self.treesort = self.treeview.get_model()
            self.treefilter = self.treesort.get_model()
            self.liststore = self.treefilter.get_model()
            for x in range(0, self.liststore.get_n_columns()):
                col = self.treeview.get_column(x)
                if col:
                    cell = col.get_cells()[0]
                    if isinstance(cell, Gtk.CellRendererText):
                        self.liststore.set_sort_func(x, self.stripsort, None)
            self.treeview.get_selection().unselect_all()
        self.modify_button.set_sensitive(False)

    def stripsort(self, model, row1, row2, user_data):
        sort_column, _ = model.get_sort_column_id()
        val1 = self.unmarkup(model.get_value(row1, sort_column))
        val2 = self.unmarkup(model.get_value(row2, sort_column))
        return cmp(val1, val2)

    def display_more_detail(self, windows, path):
        it = self.boolean_filter.get_iter(path)
        it = self.boolean_filter.convert_iter_to_child_iter(it)

        self.boolean_more_detail_tree_data_set.clear()
        self.boolean_more_detail_window.set_title(_("Boolean %s Allow Rules") % self.boolean_liststore.get_value(it, 2))
        blist = sepolicy.get_boolean_rules(self.application, self.boolean_liststore.get_value(it, 2))
        for b in blist:
            self.display_more_detail_init(b["source"], b["target"], b["class"], b["permlist"])
        self.show_popup(self.boolean_more_detail_window)

    def display_more_detail_init(self, source, target, class_type, permission):
        iter = self.boolean_more_detail_tree_data_set.append()
        self.boolean_more_detail_tree_data_set.set_value(iter, 0, "allow %s %s:%s { %s };" % (source, target, class_type, " ".join(permission)))

    def add_button_clicked(self, *args):
        self.modify = False
        if self.opage == NETWORK_PAGE:
            self.popup_network_label.set_text((_("Add Network Port for %s.  Ports will be created when update is applied.")) % self.application)
            self.network_popup_window.set_title((_("Add Network Port for %s")) % self.application)
            self.init_network_dialog(args)
            return

        if self.opage == FILES_PAGE:
            self.popup_files_label.set_text((_("Add File Labeling for %s. File labels will be created when update is applied.")) % self.application)
            self.files_popup_window.set_title((_("Add File Labeling for %s")) % self.application)
            self.init_files_dialog(args)
            ipage = self.inner_notebook_files.get_current_page()
            if ipage == EXE_PAGE:
                self.files_path_entry.set_text("ex: /usr/sbin/Foobar")
            else:
                self.files_path_entry.set_text("ex: /var/lib/Foobar")
            self.clear_entry = True

        if self.opage == LOGIN_PAGE:
            self.login_label.set_text((_("Add Login Mapping. User Mapping will be created when Update is applied.")))
            self.login_popup_window.set_title(_("Add Login Mapping"))
            self.login_init_dialog(args)
            self.clear_entry = True

        if self.opage == USER_PAGE:
            self.user_label.set_text((_("Add SELinux User Role. SELinux user roles will be created when update is applied.")))
            self.user_popup_window.set_title(_("Add SELinux Users"))
            self.user_init_dialog(args)
            self.clear_entry = True

        if self.opage == FILE_EQUIV_PAGE:
            self.file_equiv_source_entry.set_text("")
            self.file_equiv_dest_entry.set_text("")
            self.file_equiv_label.set_text((_("Add File Equivalency Mapping. Mapping will be created when update is applied.")))
            self.file_equiv_popup_window.set_title(_("Add SELinux File Equivalency"))
            self.clear_entry = True
            self.show_popup(self.file_equiv_popup_window)

        self.new_updates()

    def show_popup(self, window):
        self.current_popup = window
        window.show()

    def close_popup(self, *args):
        self.current_popup.hide()
        self.window.set_sensitive(True)
        return True

    def modify_button_clicked(self, *args):
        iter = None
        if self.treeview:
            iter = self.get_selected_iter()
            if not iter:
                self.modify_button.set_sensitive(False)
                return
        self.modify = True
        if self.opage == NETWORK_PAGE:
            self.modify_button_network_clicked(args)

        if self.opage == FILES_PAGE:
            self.popup_files_label.set_text((_("Modify File Labeling for %s. File labels will be created when update is applied.")) % self.application)
            self.files_popup_window.set_title((_("Add File Labeling for %s")) % self.application)
            self.delete_old_item = None
            self.init_files_dialog(args)
            self.modify = True
            operation = "Modify"
            mls = 1
            ipage = self.inner_notebook_files.get_current_page()

            if ipage == EXE_PAGE:
                iter = self.executable_files_filter.convert_iter_to_child_iter(iter)
                self.delete_old_item = iter
                path = self.executable_files_liststore.get_value(iter, 0)
                self.files_path_entry.set_text(path)
                ftype = self.executable_files_liststore.get_value(iter, 1)
                if ftype != None:
                    self.combo_set_active_text(self.files_type_combobox, ftype)
                tclass = self.executable_files_liststore.get_value(iter, 2)
                if tclass != None:
                    self.combo_set_active_text(self.files_class_combobox, tclass)

            if ipage == WRITABLE_PAGE:
                iter = self.writable_files_filter.convert_iter_to_child_iter(iter)
                self.delete_old_item = iter
                path = self.writable_files_liststore.get_value(iter, 0)
                self.files_path_entry.set_text(path)
                type = self.writable_files_liststore.get_value(iter, 1)
                if type != None:
                    self.combo_set_active_text(self.files_type_combobox, type)
                tclass = self.writable_files_liststore.get_value(iter, 2)
                if tclass != None:
                    self.combo_set_active_text(self.files_class_combobox, tclass)

            if ipage == APP_PAGE:
                iter = self.application_files_filter.convert_iter_to_child_iter(iter)
                self.delete_old_item = iter
                path = self.application_files_liststore.get_value(iter, 0)
                self.files_path_entry.set_text(path)
                try:
                    get_type = self.application_files_liststore.get_value(iter, 1)
                    get_type = get_type.split("<b>")[1].split("</b>")
                except AttributeError:
                    pass
                type = self.application_files_liststore.get_value(iter, 2)
                if type != None:
                    self.combo_set_active_text(self.files_type_combobox, type)
                tclass = get_type[0]
                if tclass != None:
                    self.combo_set_active_text(self.files_class_combobox, tclass)

        if self.opage == USER_PAGE:
            self.user_init_dialog(args)
            self.user_name_entry.set_text(self.user_liststore.get_value(iter, 0))
            self.user_mls_level_entry.set_text(self.user_liststore.get_value(iter, 2))
            self.user_mls_entry.set_text(self.user_liststore.get_value(iter, 3))
            self.combo_set_active_text(self.user_roles_combobox, self.user_liststore.get_value(iter, 1))
            self.user_label.set_text((_("Modify SELinux User Role. SELinux user roles will be modified when update is applied.")))
            self.user_popup_window.set_title(_("Modify SELinux Users"))
            self.show_popup(self.user_popup_window)

        if self.opage == LOGIN_PAGE:
            self.login_init_dialog(args)
            self.login_name_entry.set_text(self.login_liststore.get_value(iter, 0))
            self.login_mls_entry.set_text(self.login_liststore.get_value(iter, 2))
            self.combo_set_active_text(self.login_seuser_combobox, self.login_liststore.get_value(iter, 1))
            self.login_label.set_text((_("Modify Login Mapping. Login Mapping will be modified when Update is applied.")))
            self.login_popup_window.set_title(_("Modify Login Mapping"))
            self.show_popup(self.login_popup_window)

        if self.opage == FILE_EQUIV_PAGE:
            self.file_equiv_source_entry.set_text(self.unmarkup(self.file_equiv_liststore.get_value(iter, 0)))
            self.file_equiv_dest_entry.set_text(self.unmarkup(self.file_equiv_liststore.get_value(iter, 1)))
            self.file_equiv_label.set_text((_("Modify File Equivalency Mapping. Mapping will be created when update is applied.")))
            self.file_equiv_popup_window.set_title(_("Modify SELinux File Equivalency"))
            self.clear_entry = True
            self.show_popup(self.file_equiv_popup_window)

    def populate_type_combo(self, tree, loc, *args):
        iter = self.more_types_files_liststore.get_iter(loc)
        ftype = self.more_types_files_liststore.get_value(iter, 0)
        self.combo_set_active_text(self.files_type_combobox, ftype)
        self.show_popup(self.files_popup_window)
        self.moreTypes_window_files.hide()

    def strip_domain(self, domain):
        if domain == None:
            return
        if domain.endswith("_script_t"):
            split_char = "_script_t"
        else:
            split_char = "_t"
        return domain.split(split_char)[0]

    def exclude_type(self, type, exclude_list):
        for e in exclude_list:
            if type.startswith(e):
                return True
        return False

    def init_files_dialog(self, *args):
        exclude_list = []
        self.files_class_combobox.set_sensitive(True)
        self.show_popup(self.files_popup_window)
        ipage = self.inner_notebook_files.get_current_page()
        self.files_type_combolist.clear()
        self.files_class_combolist.clear()
        compare = self.strip_domain(self.application)
        for d in self.application_liststore:
            if d[0].startswith(compare) and d[0] != self.application and not d[0].startswith("httpd_sys"):
                exclude_list.append(self.strip_domain(d[0]))

        self.more_types_files_liststore.clear()
        try:
            for files in sepolicy.file_type_str:
                iter = self.files_class_combolist.append()
                self.files_class_combolist.set_value(iter, 0, sepolicy.file_type_str[files])

            if ipage == EXE_PAGE and self.entrypoints != None:
                for exe in self.entrypoints.keys():
                    if exe.startswith(compare):
                        iter = self.files_type_combolist.append()
                        self.files_type_combolist.set_value(iter, 0, exe)
                    iter = self.more_types_files_liststore.append()
                    self.more_types_files_liststore.set_value(iter, 0, exe)
                self.files_class_combobox.set_active(4)
                self.files_class_combobox.set_sensitive(False)

            elif ipage == WRITABLE_PAGE and self.writable_files != None:
                for write in self.writable_files.keys():
                    if write.startswith(compare) and not self.exclude_type(write, exclude_list) and write in self.file_types:
                        iter = self.files_type_combolist.append()
                        self.files_type_combolist.set_value(iter, 0, write)
                    iter = self.more_types_files_liststore.append()
                    self.more_types_files_liststore.set_value(iter, 0, write)
                self.files_class_combobox.set_active(0)
            elif ipage == APP_PAGE and self.file_types != None:
                for app in sepolicy.get_all_file_types():
                    if app.startswith(compare):
                        if app.startswith(compare) and not self.exclude_type(app, exclude_list):
                            iter = self.files_type_combolist.append()
                            self.files_type_combolist.set_value(iter, 0, app)
                        iter = self.more_types_files_liststore.append()
                        self.more_types_files_liststore.set_value(iter, 0, app)
                self.files_class_combobox.set_active(0)
        except AttributeError:
            print("error")
            pass
        self.files_type_combobox.set_active(0)
        self.files_mls_entry.set_text("s0")
        iter = self.files_type_combolist.append()
        self.files_type_combolist.set_value(iter, 0, _('More...'))

    def modify_button_network_clicked(self, *args):
        iter = self.get_selected_iter()
        if not iter:
            self.modify_button.set_sensitive(False)
            return

        self.popup_network_label.set_text((_("Modify Network Port for %s.  Ports will be created when update is applied.")) % self.application)
        self.network_popup_window.set_title((_("Modify Network Port for %s")) % self.application)
        self.delete_old_item = None
        self.init_network_dialog(args)
        operation = "Modify"
        mls = 1
        self.modify = True
        iter = self.get_selected_iter()
        port = self.liststore.get_value(iter, 0)
        self.network_ports_entry.set_text(port)
        protocol = self.liststore.get_value(iter, 1)
        if protocol == "tcp":
            self.network_tcp_button.set_active(True)
        elif protocol == "udp":
            self.network_udp_button.set_active(True)
        type = self.liststore.get_value(iter, 2)
        if type != None:
            self.combo_set_active_text(self.network_port_type_combobox, type)
        self.delete_old_item = iter

    def init_network_dialog(self, *args):
        self.show_popup(self.network_popup_window)
        ipage = self.inner_notebook_network.get_current_page()
        self.network_port_type_combolist.clear()
        self.network_ports_entry.set_text("")

        try:
            if ipage == OUTBOUND_PAGE:
                netd = sepolicy.network.get_network_connect(self.application, "tcp", "name_connect", check_bools=True)
            elif ipage == INBOUND_PAGE:
                netd = sepolicy.network.get_network_connect(self.application, "tcp", "name_bind", check_bools=True)
                netd += sepolicy.network.get_network_connect(self.application, "udp", "name_bind", check_bools=True)

            port_types = []
            for k in netd.keys():
                for t, ports in netd[k]:
                    if t not in port_types + ["port_t", "unreserved_port_t"]:
                        if t.endswith("_type"):
                            continue

                        port_types.append(t)

            port_types.sort()
            short_domain = self.strip_domain(self.application)
            if short_domain[-1] == "d":
                short_domain = short_domain[:-1]
            short_domain = short_domain + "_"
            ctr = 0
            found = 0
            for t in port_types:
                if t.startswith(short_domain):
                    found = ctr
                iter = self.network_port_type_combolist.append()
                self.network_port_type_combolist.set_value(iter, 0, t)
                ctr += 1
            self.network_port_type_combobox.set_active(found)

        except AttributeError:
            pass

        self.network_tcp_button.set_active(True)
        self.network_mls_entry.set_text("s0")

    def login_seuser_combobox_change(self, combo, *args):
        seuser = self.combo_get_active_text(combo)
        if self.login_mls_entry.get_text() == "":
            for u in sepolicy.get_selinux_users():
                if seuser == u['name']:
                    self.login_mls_entry.set_text(u.get('range', ''))

    def user_roles_combobox_change(self, combo, *args):
        serole = self.combo_get_active_text(combo)
        if self.user_mls_entry.get_text() == "":
            for u in sepolicy.get_all_roles():
                if serole == u['name']:
                    self.user_mls_entry.set_text(u.get('range', ''))

    def get_selected_iter(self):
        iter = None
        if not self.treeview:
            return None
        row = self.treeview.get_selection()
        if not row:
            return None
        treesort, iter = row.get_selected()
        if iter:
            iter = treesort.convert_iter_to_child_iter(iter)
            if iter:
                iter = self.treefilter.convert_iter_to_child_iter(iter)
        return iter

    def cursor_changed(self, *args):
        self.modify_button.set_sensitive(False)
        iter = self.get_selected_iter()
        if iter == None:
            self.modify_button.set_sensitive(False)
            return
        if not self.liststore[iter] or not self.liststore[iter][-1]:
            return
        self.modify_button.set_sensitive(self.liststore[iter][-1])

    def login_init_dialog(self, *args):
        self.show_popup(self.login_popup_window)
        self.login_seuser_combolist.clear()
        users = sepolicy.get_all_users()
        users.sort()
        for u in users:
            iter = self.login_seuser_combolist.append()
            self.login_seuser_combolist.set_value(iter, 0, str(u))
        self.login_name_entry.set_text("")
        self.login_mls_entry.set_text("")

    def user_init_dialog(self, *args):
        self.show_popup(self.user_popup_window)
        self.user_roles_combolist.clear()
        roles = sepolicy.get_all_roles()
        roles.sort()
        for r in roles:
            iter = self.user_roles_combolist.append()
            self.user_roles_combolist.set_value(iter, 0, str(r))
        self.user_name_entry.set_text("")
        self.user_mls_entry.set_text("")

    def on_disable_ptrace(self, checkbutton):
        if self.finish_init:
            update_buffer = "boolean -m -%d deny_ptrace" % checkbutton.get_active()
            self.wait_mouse()
            try:
                self.dbus.semanage(update_buffer)
            except dbus.exceptions.DBusException as e:
                self.error(e)
            self.ready_mouse()

    def on_show_modified_only(self, checkbutton):
        length = self.liststore.get_n_columns()

        def dup_row(row):
            l = []
            for i in range(0, length):
                l.append(row[i])
            return l

        append_list = []
        if self.opage == BOOLEANS_PAGE:
            if not checkbutton.get_active():
                return self.boolean_initialize(self.application)

            for row in self.liststore:
                if row[2] in self.cust_dict["boolean"]:
                    append_list.append(dup_row(row))

        if self.opage == FILES_PAGE:
            ipage = self.inner_notebook_files.get_current_page()
            if not checkbutton.get_active():
                if ipage == EXE_PAGE:
                    return self.executable_files_initialize(self.application)
                if ipage == WRITABLE_PAGE:
                    return self.writable_files_initialize(self.application)
                if ipage == APP_PAGE:
                    return self.application_files_initialize(self.application)
            for row in self.liststore:
                if (row[0], row[2]) in self.cust_dict["fcontext"]:
                    append_list.append(row)

        if self.opage == NETWORK_PAGE:
            if not checkbutton.get_active():
                return self.network_initialize(self.application)
            for row in self.liststore:
                if (row[0], row[1]) in self.cust_dict["port"]:
                    append_list.append(dup_row(row))

        if self.opage == FILE_EQUIV_PAGE:
            if not checkbutton.get_active() == True:
                return self.file_equiv_initialize()

            for row in self.liststore:
                if row[0] in self.cust_dict["fcontext-equiv"]:
                    append_list.append(dup_row(row))

        if self.opage == USER_PAGE:
            if not checkbutton.get_active():
                return self.user_initialize()

            for row in self.liststore:
                if row[0] in self.cust_dict["user"]:
                    append_list.append(dup_row(row))

        if self.opage == LOGIN_PAGE:
            if not checkbutton.get_active() == True:
                return self.login_initialize()

            for row in self.liststore:
                if row[0] in self.cust_dict["login"]:
                    append_list.append(dup_row(row))

        self.liststore.clear()
        for row in append_list:
            iter = self.liststore.append()
            for i in range(0, length):
                self.liststore.set_value(iter, i, row[i])

    def init_modified_files_liststore(self, tree, app, ipage, operation, path, fclass, ftype):
        iter = tree.append(None)
        tree.set_value(iter, 0, path)
        tree.set_value(iter, 1, ftype)
        tree.set_value(iter, 2, fclass)

    def restore_to_default(self, *args):
        print("restore to default clicked...")

    def invalid_entry_retry(self, *args):
        self.closewindow(self.error_check_window)
        self.files_popup_window.set_sensitive(True)
        self.network_popup_window.set_sensitive(True)

    def error_check_files(self, insert_txt):
        if len(insert_txt) == 0 or insert_txt[0] != '/':
            self.error_check_window.show()
            self.files_popup_window.set_sensitive(False)
            self.network_popup_window.set_sensitive(False)
            self.error_check_label.set_text((_("The entry '%s' is not a valid path.  Paths must begin with a '/'.")) % insert_txt)
            return True
        return False

    def error_check_network(self, port):
        try:
            pnum = int(port)
            if pnum < 1 or pnum > 65536:
                raise ValueError
        except ValueError:
            self.error_check_window.show()
            self.files_popup_window.set_sensitive(False)
            self.network_popup_window.set_sensitive(False)
            self.error_check_label.set_text((_("Port number must be between 1 and 65536")))
            return True
        return False

    def show_more_types(self, *args):
        if self.finish_init:
            if self.combo_get_active_text(self.files_type_combobox) == _('More...'):
                self.files_popup_window.hide()
                self.moreTypes_window_files.show()

    def update_to_login(self, *args):
        self.close_popup()
        seuser = self.combo_get_active_text(self.login_seuser_combobox)
        mls_range = self.login_mls_entry.get_text()
        name = self.login_name_entry.get_text()
        if self.modify:
            iter = self.get_selected_iter()
            oldname = self.login_liststore.get_value(iter, 0)
            oldseuser = self.login_liststore.get_value(iter, 1)
            oldrange = self.login_liststore.get_value(iter, 2)
            self.liststore.set_value(iter, 0, oldname)
            self.liststore.set_value(iter, 1, oldseuser)
            self.liststore.set_value(iter, 2, oldrange)
            self.cur_dict["login"][name] = {"action": "-m", "range": mls_range, "seuser": seuser, "oldrange": oldrange, "oldseuser": oldseuser, "oldname": oldname}
        else:
            iter = self.liststore.append(None)
            self.cur_dict["login"][name] = {"action": "-a", "range": mls_range, "seuser": seuser}

        self.liststore.set_value(iter, 0, name)
        self.liststore.set_value(iter, 1, seuser)
        self.liststore.set_value(iter, 2, mls_range)

        self.new_updates()

    def update_to_user(self, *args):
        self.close_popup()
        roles = self.combo_get_active_text(self.user_roles_combobox)
        level = self.user_mls_level_entry.get_text()
        mls_range = self.user_mls_entry.get_text()
        name = self.user_name_entry.get_text()
        if self.modify:
            iter = self.get_selected_iter()
            oldname = self.user_liststore.get_value(iter, 0)
            oldroles = self.user_liststore.get_value(iter, 1)
            oldlevel = self.user_liststore.get_value(iter, 1)
            oldrange = self.user_liststore.get_value(iter, 3)
            self.liststore.set_value(iter, 0, oldname)
            self.liststore.set_value(iter, 1, oldroles)
            self.liststore.set_value(iter, 2, oldlevel)
            self.liststore.set_value(iter, 3, oldrange)
            self.cur_dict["user"][name] = {"action": "-m", "range": mls_range, "level": level, "role": roles, "oldrange": oldrange, "oldlevel": oldlevel, "oldroles": oldroles, "oldname": oldname}
        else:
            iter = self.liststore.append(None)
            if mls_range or level:
                self.cur_dict["user"][name] = {"action": "-a", "range": mls_range, "level": level, "role": roles}
            else:
                self.cur_dict["user"][name] = {"action": "-a", "role": roles}

        self.liststore.set_value(iter, 0, name)
        self.liststore.set_value(iter, 1, roles)
        self.liststore.set_value(iter, 2, level)
        self.liststore.set_value(iter, 3, mls_range)

        self.new_updates()

    def update_to_file_equiv(self, *args):
        self.close_popup()
        dest = self.file_equiv_dest_entry.get_text()
        src = self.file_equiv_source_entry.get_text()
        if self.modify:
            iter = self.get_selected_iter()
            olddest = self.unmarkup(self.liststore.set_value(iter, 0))
            oldsrc = self.unmarkup(self.liststore.set_value(iter, 1))
            self.cur_dict["fcontext-equiv"][dest] = {"action": "-m", "src": src, "oldsrc": oldsrc, "olddest": olddest}
        else:
            iter = self.liststore.append(None)
            self.cur_dict["fcontext-equiv"][dest] = {"action": "-a", "src": src}
        self.liststore.set_value(iter, 0, self.markup(dest))
        self.liststore.set_value(iter, 1, self.markup(src))

    def update_to_files(self, *args):
        self.close_popup()
        self.files_add = True
        # Insert Function will be used in the future
        path = self.files_path_entry.get_text()
        if self.error_check_files(path):
            return

        setype = self.combo_get_active_text(self.files_type_combobox)
        mls = self.files_mls_entry.get_text()
        tclass = self.combo_get_active_text(self.files_class_combobox)

        if self.modify:
            iter = self.get_selected_iter()
            oldpath = self.unmark(self.liststore.get_value(iter, 0))
            oldsetype = self.unmark(self.liststore.set_value(iter, 1))
            oldtclass = self.liststore.get_value(iter, 2)
            self.cur_dict["fcontext"][(path, tclass)] = {"action": "-m", "type": setype, "oldtype": oldsetype, "oldpath": oldpath, "oldclass": oldtclass}
        else:
            iter = self.liststore.append(None)
            self.cur_dict["fcontext"][(path, tclass)] = {"action": "-a", "type": setype}
        self.liststore.set_value(iter, 0, self.markup(path))
        self.liststore.set_value(iter, 1, self.markup(setype))
        self.liststore.set_value(iter, 2, self.markup(tclass))

        self.files_add = False
        self.recursive_path_toggle.set_active(False)
        self.new_updates()

    def update_to_network(self, *args):
        self.network_add = True
        ports = self.network_ports_entry.get_text()
        if self.error_check_network(ports):
            return
        if self.network_tcp_button.get_active():
            protocol = "tcp"
        else:
            protocol = "udp"

        setype = self.combo_get_active_text(self.network_port_type_combobox)
        mls = self.network_mls_entry.get_text()

        if self.modify:
            iter = self.get_selected_iter()
            oldports = self.unmark(self.liststore.get_value(iter, 0))
            oldprotocol = self.unmark(self.liststore.get_value(iter, 1))
            oldsetype = self.unmark(self.liststore.set_value(iter, 2))
            self.cur_dict["port"][(ports, protocol)] = {"action": "-m", "type": setype, "mls": mls, "oldtype": oldsetype, "oldprotocol": oldprotocol, "oldports": oldports}
        else:
            iter = self.liststore.append(None)
            self.cur_dict["port"][(ports, protocol)] = {"action": "-a", "type": setype, "mls": mls}
        self.liststore.set_value(iter, 0, ports)
        self.liststore.set_value(iter, 1, protocol)
        self.liststore.set_value(iter, 2, setype)

        self.network_add = False
        self.network_popup_window.hide()
        self.window.set_sensitive(True)
        self.new_updates()

    def delete_button_clicked(self, *args):
        operation = "Add"
        self.window.set_sensitive(False)
        if self.opage == NETWORK_PAGE:
            self.network_delete_liststore.clear()
            port_dict = self.cust_dict["port"]
            for ports, protocol in port_dict:
                setype = port_dict[(ports, protocol)]["type"]
                iter = self.network_delete_liststore.append()
                self.network_delete_liststore.set_value(iter, 1, ports)
                self.network_delete_liststore.set_value(iter, 2, protocol)
                self.network_delete_liststore.set_value(iter, 3, setype)
            self.show_popup(self.network_delete_window)
            return

        if self.opage == FILES_PAGE:
            self.files_delete_liststore.clear()
            fcontext_dict = self.cust_dict["fcontext"]
            for path, tclass in fcontext_dict:
                setype = fcontext_dict[(path, tclass)]["type"]
                iter = self.files_delete_liststore.append()
                self.files_delete_liststore.set_value(iter, 1, path)
                self.files_delete_liststore.set_value(iter, 2, setype)
                self.files_delete_liststore.set_value(iter, 3, sepolicy.file_type_str[tclass])
            self.show_popup(self.files_delete_window)
            return

        if self.opage == USER_PAGE:
            self.user_delete_liststore.clear()
            user_dict = self.cust_dict["user"]
            for user in user_dict:
                roles = user_dict[user]["role"]
                mls = user_dict[user].get("range", "")
                level = user_dict[user].get("level", "")
                iter = self.user_delete_liststore.append()
                self.user_delete_liststore.set_value(iter, 1, user)
                self.user_delete_liststore.set_value(iter, 2, roles)
                self.user_delete_liststore.set_value(iter, 3, level)
                self.user_delete_liststore.set_value(iter, 4, mls)
            self.show_popup(self.user_delete_window)
            return

        if self.opage == LOGIN_PAGE:
            self.login_delete_liststore.clear()
            login_dict = self.cust_dict["login"]
            for login in login_dict:
                seuser = login_dict[login]["seuser"]
                mls = login_dict[login].get("range", "")
                iter = self.login_delete_liststore.append()
                self.login_delete_liststore.set_value(iter, 1, seuser)
                self.login_delete_liststore.set_value(iter, 2, login)
                self.login_delete_liststore.set_value(iter, 3, mls)
            self.show_popup(self.login_delete_window)
            return

        if self.opage == FILE_EQUIV_PAGE:
            self.file_equiv_delete_liststore.clear()
            for items in self.file_equiv_liststore:
                if items[2]:
                    iter = self.file_equiv_delete_liststore.append()
                    self.file_equiv_delete_liststore.set_value(iter, 1, self.unmarkup(items[0]))
                    self.file_equiv_delete_liststore.set_value(iter, 2, self.unmarkup(items[1]))
            self.show_popup(self.file_equiv_delete_window)
            return

    def on_save_delete_clicked(self, *args):
        self.close_popup()
        if self.opage == NETWORK_PAGE:
            for delete in self.network_delete_liststore:
                if delete[0]:
                    self.cur_dict["port"][(delete[1], delete[2])] = {"action": "-d", "type": delete[3]}
        if self.opage == FILES_PAGE:
            for delete in self.files_delete_liststore:
                if delete[0]:
                    self.cur_dict["fcontext"][(delete[1], reverse_file_type_str[delete[3]])] = {"action": "-d", "type": delete[2]}
        if self.opage == USER_PAGE:
            for delete in self.user_delete_liststore:
                if delete[0]:
                    self.cur_dict["user"][delete[1]] = {"action": "-d", "role": delete[2], "range": delete[4]}
        if self.opage == LOGIN_PAGE:
            for delete in self.login_delete_liststore:
                if delete[0]:
                    self.cur_dict["login"][delete[2]] = {"action": "-d", "login": delete[2], "seuser": delete[1], "range": delete[3]}
        if self.opage == FILE_EQUIV_PAGE:
            for delete in self.file_equiv_delete_liststore:
                if delete[0]:
                    self.cur_dict["fcontext-equiv"][delete[1]] = {"action": "-d", "src": delete[2]}
        self.new_updates()

    def on_save_delete_file_equiv_clicked(self, *args):
        for delete in self.files_delete_liststore:
            print(delete[0], delete[1], delete[2],)

    def on_toggle_update(self, cell, path, model):
        model[path][0] = not model[path][0]

    def ipage_delete(self, liststore, key):
        ctr = 0
        for items in liststore:
            if items[0] == key[0] and items[2] == key[1]:
                iter = liststore.get_iter(ctr)
                liststore.remove(iter)
                return
            ctr += 1

    def on_toggle(self, cell, path, model):
        if not path:
            return
        iter = self.boolean_filter.get_iter(path)
        iter = self.boolean_filter.convert_iter_to_child_iter(iter)
        name = model.get_value(iter, 2)
        model.set_value(iter, 0, not model.get_value(iter, 0))
        active = model.get_value(iter, 0)
        if name in self.cur_dict["boolean"]:
            del self.cur_dict["boolean"][name]
        else:
            self.cur_dict["boolean"][name] = {"active": active}
        self.new_updates()

    def get_advanced_filter_data(self, entry, *args):
        self.filter_txt = entry.get_text()
        self.advanced_search_filter.refilter()

    def get_filter_data(self, windows, *args):
        #search for desired item
        # The txt that the use rinputs into the filter is stored in filter_txt
        self.filter_txt = windows.get_text()
        self.treefilter.refilter()

    def update_gui(self, *args):
        self.update = True
        self.update_treestore.clear()
        for bools in self.cur_dict["boolean"]:
            operation = self.cur_dict["boolean"][bools]["action"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 1, sepolicy.boolean_desc(bools))
            self.update_treestore.set_value(iter, 2, action[self.cur_dict["boolean"][bools]['active']])
            self.update_treestore.set_value(iter, 3, True)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 1, (_("SELinux name: %s")) % bools)
            self.update_treestore.set_value(niter, 3, False)

        for path, tclass in self.cur_dict["fcontext"]:
            operation = self.cur_dict["fcontext"][(path, tclass)]["action"]
            setype = self.cur_dict["fcontext"][(path, tclass)]["type"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 2, operation)
            self.update_treestore.set_value(iter, 0, True)
            if operation == "-a":
                self.update_treestore.set_value(iter, 1, (_("Add file labeling for %s")) % self.application)
            if operation == "-d":
                self.update_treestore.set_value(iter, 1, (_("Delete file labeling for %s")) % self.application)
            if operation == "-m":
                self.update_treestore.set_value(iter, 1, (_("Modify file labeling for %s")) % self.application)

            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("File path: %s")) % path)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("File class: %s")) % sepolicy.file_type_str[tclass])
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("SELinux file type: %s")) % setype)

        for port, protocol in self.cur_dict["port"]:
            operation = self.cur_dict["port"][(port, protocol)]["action"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 2, operation)
            self.update_treestore.set_value(iter, 3, True)
            if operation == "-a":
                self.update_treestore.set_value(iter, 1, (_("Add ports for %s")) % self.application)
            if operation == "-d":
                self.update_treestore.set_value(iter, 1, (_("Delete ports for %s")) % self.application)
            if operation == "-m":
                self.update_treestore.set_value(iter, 1, (_("Modify ports for %s")) % self.application)

            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 1, (_("Network ports: %s")) % port)
            self.update_treestore.set_value(niter, 3, False)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 1, (_("Network protocol: %s")) % protocol)
            self.update_treestore.set_value(niter, 3, False)
            setype = self.cur_dict["port"][(port, protocol)]["type"]
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("SELinux file type: %s")) % setype)

        for user in self.cur_dict["user"]:
            operation = self.cur_dict["user"][user]["action"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 2, operation)
            self.update_treestore.set_value(iter, 0, True)
            if operation == "-a":
                self.update_treestore.set_value(iter, 1, _("Add user"))
            if operation == "-d":
                self.update_treestore.set_value(iter, 1, _("Delete user"))
            if operation == "-m":
                self.update_treestore.set_value(iter, 1, _("Modify user"))

            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 1, (_("SELinux User : %s")) % user)
            self.update_treestore.set_value(niter, 3, False)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            roles = self.cur_dict["user"][user]["role"]
            self.update_treestore.set_value(niter, 1, (_("Roles: %s")) % roles)
            mls = self.cur_dict["user"][user].get("range", "")
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, _("MLS/MCS Range: %s") % mls)

        for login in self.cur_dict["login"]:
            operation = self.cur_dict["login"][login]["action"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 2, operation)
            self.update_treestore.set_value(iter, 0, True)
            if operation == "-a":
                self.update_treestore.set_value(iter, 1, _("Add login mapping"))
            if operation == "-d":
                self.update_treestore.set_value(iter, 1, _("Delete login mapping"))
            if operation == "-m":
                self.update_treestore.set_value(iter, 1, _("Modify login mapping"))

            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("Login Name : %s")) % login)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            seuser = self.cur_dict["login"][login]["seuser"]
            self.update_treestore.set_value(niter, 1, (_("SELinux User: %s")) % seuser)
            mls = self.cur_dict["login"][login].get("range", "")
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, _("MLS/MCS Range: %s") % mls)

        for path in self.cur_dict["fcontext-equiv"]:
            operation = self.cur_dict["fcontext-equiv"][path]["action"]
            iter = self.update_treestore.append(None)
            self.update_treestore.set_value(iter, 0, True)
            self.update_treestore.set_value(iter, 2, operation)
            self.update_treestore.set_value(iter, 0, True)
            if operation == "-a":
                self.update_treestore.set_value(iter, 1, (_("Add file equiv labeling.")))
            if operation == "-d":
                self.update_treestore.set_value(iter, 1, (_("Delete file equiv labeling.")))
            if operation == "-m":
                self.update_treestore.set_value(iter, 1, (_("Modify file equiv labeling.")))

            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            self.update_treestore.set_value(niter, 1, (_("File path : %s")) % path)
            niter = self.update_treestore.append(iter)
            self.update_treestore.set_value(niter, 3, False)
            src = self.cur_dict["fcontext-equiv"][path]["src"]
            self.update_treestore.set_value(niter, 1, (_("Equivalence: %s")) % src)

        self.show_popup(self.update_window)

    def set_active_application_button(self):
        if self.boolean_radio_button.get_active():
            self.active_button = self.boolean_radio_button
        if self.files_radio_button.get_active():
            self.active_button = self.files_radio_button
        if self.transitions_radio_button.get_active():
            self.active_button = self.transitions_radio_button
        if self.network_radio_button.get_active():
            self.active_button = self.network_radio_button

    def clearbuttons(self, clear=True):
        self.main_selection_popover.hide()
        self.boolean_radio_button.set_visible(False)
        self.files_radio_button.set_visible(False)
        self.network_radio_button.set_visible(False)
        self.transitions_radio_button.set_visible(False)
        self.system_radio_button.set_visible(False)
        self.lockdown_radio_button.set_visible(False)
        self.user_radio_button.set_visible(False)
        self.login_radio_button.set_visible(False)
        if clear:
            self.completion_entry.set_text("")

    def show_system_page(self):
        self.clearbuttons()
        self.system_radio_button.set_visible(True)
        self.lockdown_radio_button.set_visible(True)
        self.applications_selection_button.set_label(_("System"))
        self.system_radio_button.set_active(True)
        self.tab_change()
        self.idle_func()

    def show_file_equiv_page(self, *args):
        self.clearbuttons()
        self.file_equiv_initialize()
        self.file_equiv_radio_button.set_active(True)
        self.applications_selection_button.set_label(_("File Equivalence"))
        self.tab_change()
        self.idle_func()
        self.add_button.set_sensitive(True)
        self.delete_button.set_sensitive(True)

    def show_users_page(self):
        self.clearbuttons()
        self.login_radio_button.set_visible(True)
        self.user_radio_button.set_visible(True)
        self.applications_selection_button.set_label(_("Users"))
        self.login_radio_button.set_active(True)
        self.tab_change()
        self.user_initialize()
        self.login_initialize()
        self.idle_func()
        self.add_button.set_sensitive(True)
        self.delete_button.set_sensitive(True)

    def show_applications_page(self):
        self.clearbuttons(False)
        self.boolean_radio_button.set_visible(True)
        self.files_radio_button.set_visible(True)
        self.network_radio_button.set_visible(True)
        self.transitions_radio_button.set_visible(True)
        self.boolean_radio_button.set_active(True)
        self.tab_change()
        self.idle_func()

    def system_interface(self, *args):
        self.show_system_page()

    def users_interface(self, *args):
        self.show_users_page()

    def show_mislabeled_files(self, checkbutton, *args):
        iterlist = []
        ctr = 0
        ipage = self.inner_notebook_files.get_current_page()
        if checkbutton.get_active() == True:
            for items in self.liststore:
                iter = self.treesort.get_iter(ctr)
                iter = self.treesort.convert_iter_to_child_iter(iter)
                iter = self.treefilter.convert_iter_to_child_iter(iter)
                if iter != None:
                    if self.liststore.get_value(iter, 4) == False:
                        iterlist.append(iter)
                    ctr += 1
            for iters in iterlist:
                self.liststore.remove(iters)

        elif self.application != None:
            self.liststore.clear()
            if ipage == EXE_PAGE:
                self.executable_files_initialize(self.application)
            elif ipage == WRITABLE_PAGE:
                self.writable_files_initialize(self.application)
            elif ipage == APP_PAGE:
                self.application_files_initialize(self.application)

    def fix_mislabeled(self, path):
        cur = selinux.getfilecon(path)[1].split(":")[2]
        con = selinux.matchpathcon(path, 0)[1].split(":")[2]
        if self.verify(_("Run restorecon on %(PATH)s to change its type from %(CUR_CONTEXT)s to the default %(DEF_CONTEXT)s?") % {"PATH": path, "CUR_CONTEXT": cur, "DEF_CONTEXT": con}, title="restorecon dialog") == Gtk.ResponseType.YES:
            self.dbus.restorecon(path)
            self.application_selected()

    def new_updates(self, *args):
        self.update_button.set_sensitive(self.modified())
        self.revert_button.set_sensitive(self.modified())

    def update_or_revert_changes(self, button, *args):
        self.update_gui()
        self.update = (button.get_label() == _("Update"))
        if self.update:
            self.update_window.set_title(_("Update Changes"))
        else:
            self.update_window.set_title(_("Revert Changes"))

    def apply_changes_button_press(self, *args):
        self.close_popup()
        if self.update:
            self.update_the_system()
        else:
            self.revert_data()
        self.finish_init = False
        self.previously_modified_initialize(self.dbus.customized())
        self.finish_init = True
        self.clear_filters()
        self.application_selected()
        self.new_updates()
        self.update_treestore.clear()

    def update_the_system(self, *args):
        self.close_popup()
        update_buffer = self.format_update()
        self.wait_mouse()
        try:
            self.dbus.semanage(update_buffer)
        except dbus.exceptions.DBusException as e:
            print(e)
        self.ready_mouse()
        self.init_cur()

    def ipage_value_lookup(self, lookup):
        ipage_values = {"Executable Files": 0, "Writable Files": 1, "Application File Type": 2, "Inbound": 1, "Outbound": 0}
        for value in ipage_values:
            if value == lookup:
                return ipage_values[value]
        return "Booleans"

    def get_attributes_update(self, attribute):
        attribute = attribute.split(": ")[1]
        bool_id = attribute.split(": ")[0]
        if bool_id == "SELinux name":
            self.bool_revert = attribute
        else:
            return attribute

    def format_update(self):
        self.revert_data()
        update_buffer = ""
        for k in self.cur_dict:
            if k in "boolean":
                for b in self.cur_dict[k]:
                    update_buffer += "boolean -m -%d %s\n" % (self.cur_dict[k][b]["active"], b)
            if k in "login":
                for l in self.cur_dict[k]:
                    if self.cur_dict[k][l]["action"] == "-d":
                        update_buffer += "login -d %s\n" % l
                    elif "range" in self.cur_dict[k][l]:
                        update_buffer += "login %s -s %s -r %s %s\n" % (self.cur_dict[k][l]["action"], self.cur_dict[k][l]["seuser"], self.cur_dict[k][l]["range"], l)
                    else:
                        update_buffer += "login %s -s %s %s\n" % (self.cur_dict[k][l]["action"], self.cur_dict[k][l]["seuser"], l)
            if k in "user":
                for u in self.cur_dict[k]:
                    if self.cur_dict[k][u]["action"] == "-d":
                        update_buffer += "user -d %s\n" % u
                    elif "level" in self.cur_dict[k][u] and "range" in self.cur_dict[k][u]:
                        update_buffer += "user %s -L %s -r %s -R %s %s\n" % (self.cur_dict[k][u]["action"], self.cur_dict[k][u]["level"], self.cur_dict[k][u]["range"], self.cur_dict[k][u]["role"], u)
                    else:
                        update_buffer += "user %s -R %s %s\n" % (self.cur_dict[k][u]["action"], self.cur_dict[k][u]["role"], u)

            if k in "fcontext-equiv":
                for f in self.cur_dict[k]:
                    if self.cur_dict[k][f]["action"] == "-d":
                        update_buffer += "fcontext -d %s\n" % f
                    else:
                        update_buffer += "fcontext %s -e %s %s\n" % (self.cur_dict[k][f]["action"], self.cur_dict[k][f]["src"], f)

            if k in "fcontext":
                for f in self.cur_dict[k]:
                    if self.cur_dict[k][f]["action"] == "-d":
                        update_buffer += "fcontext -d %s\n" % f
                    else:
                        update_buffer += "fcontext %s -t %s -f %s %s\n" % (self.cur_dict[k][f]["action"], self.cur_dict[k][f]["type"], self.cur_dict[k][f]["class"], f)

            if k in "port":
                for port, protocol in self.cur_dict[k]:
                    if self.cur_dict[k][(port, protocol)]["action"] == "-d":
                        update_buffer += "port -d -p %s %s\n" % (protocol, port)
                    else:
                        update_buffer += "port %s -t %s -p %s %s\n" % (self.cur_dict[k][f]["action"], self.cur_dict[k][f]["type"], protocol, port)

        return update_buffer

    def revert_data(self):
        ctr = 0
        remove_list = []
        update_buffer = ""
        for items in self.update_treestore:
            if not self.update_treestore[ctr][0]:
                remove_list.append(ctr)
            ctr += 1
        remove_list.reverse()
        for ctr in remove_list:
            self.remove_cur(ctr)

    def reveal_advanced_system(self, label, *args):
        advanced = label.get_text() == ADVANCED_LABEL[0]
        if advanced:
            label.set_text(ADVANCED_LABEL[1])
        else:
            label.set_text(ADVANCED_LABEL[0])
        self.system_policy_label.set_visible(advanced)
        self.system_policy_type_combobox.set_visible(advanced)

    def reveal_advanced(self, label, *args):
        advanced = label.get_text() == ADVANCED_LABEL[0]
        if advanced:
            label.set_text(ADVANCED_LABEL[1])
        else:
            label.set_text(ADVANCED_LABEL[0])
        self.files_mls_label.set_visible(advanced)
        self.files_mls_entry.set_visible(advanced)
        self.network_mls_label.set_visible(advanced)
        self.network_mls_entry.set_visible(advanced)

    def on_show_advanced_search_window(self, label, *args):
        if label.get_text() == ADVANCED_SEARCH_LABEL[1]:
            label.set_text(ADVANCED_SEARCH_LABEL[0])
            self.close_popup()
        else:
            label.set_text(ADVANCED_SEARCH_LABEL[1])
            self.show_popup(self.advanced_search_window)

    def set_enforce_text(self, value):
        if value:
            self.status_bar.push(self.context_id, _("System Status: Enforcing"))
            self.current_status_enforcing.set_active(True)
        else:
            self.status_bar.push(self.context_id, _("System Status: Permissive"))
            self.current_status_permissive.set_active(True)

    def set_enforce(self, button):
        if not self.finish_init:
            return

        self.dbus.setenforce(button.get_active())
        self.set_enforce_text(button.get_active())

    def on_browse_select(self, *args):
        filename = self.file_dialog.get_filename()
        if filename == None:
            return
        self.clear_entry = False
        self.file_dialog.hide()
        self.files_path_entry.set_text(filename)
        if self.import_export == 'Import':
            self.import_config(filename)
        elif self.import_export == 'Export':
            self.export_config(filename)

    def recursive_path(self, *args):
        path = self.files_path_entry.get_text()
        if self.recursive_path_toggle.get_active():
            if not path.endswith("(/.*)?"):
                self.files_path_entry.set_text(path + "(/.*)?")
        elif path.endswith("(/.*)?"):
            path = path.split("(/.*)?")[0]
            self.files_path_entry.set_text(path)

    def highlight_entry_text(self, entry_obj, *args):
        txt = entry_obj.get_text()
        if self.clear_entry:
            entry_obj.set_text('')
            self.clear_entry = False

    def autofill_add_files_entry(self, entry):
        text = entry.get_text()
        if text == '':
            return
        if text.endswith("(/.*)?"):
            self.recursive_path_toggle.set_active(True)
        for d in sepolicy.DEFAULT_DIRS:
            if text.startswith(d):
                for t in self.files_type_combolist:
                    if t[0].endswith(sepolicy.DEFAULT_DIRS[d]):
                        self.combo_set_active_text(self.files_type_combobox, t[0])

    def resize_columns(self, *args):
        self.boolean_column_1 = self.boolean_treeview.get_col(1)
        width = self.boolean_column_1.get_width()
        renderer = self.boolean_column_1.get_cell_renderers()

    def browse_for_files(self, *args):
        self.file_dialog.show()

    def close_config_window(self, *args):
        self.file_dialog.hide()

    def change_default_policy(self, *args):
        if self.typeHistory == self.system_policy_type_combobox.get_active():
            return

        if self.verify(_("Changing the policy type will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system.  Do you wish to continue?")) == Gtk.ResponseType.NO:
            self.system_policy_type_combobox.set_active(self.typeHistory)
            return None

        self.dbus.change_default_policy(self.combo_get_active_text(self.system_policy_type_combobox))
        self.dbus.relabel_on_boot(True)
        self.typeHistory = self.system_policy_type_combobox.get_active()

    def change_default_mode(self, button):
        if not self.finish_init:
            return
        self.enabled_changed(button)
        if button.get_active():
            self.dbus.change_default_mode(button.get_label().lower())

    def import_config_show(self, *args):
        self.file_dialog.set_action(Gtk.FileChooserAction.OPEN)
        self.file_dialog.set_title("Import Configuration")
        self.file_dialog.show()
        #self.file_dialog.set_uri('/tmp')
        self.import_export = 'Import'

    def export_config_show(self, *args):
        self.file_dialog.set_action(Gtk.FileChooserAction.SAVE)
        self.file_dialog.set_title("Export Configuration")
        self.file_dialog.show()
        self.import_export = 'Export'

    def export_config(self, filename):
        self.wait_mouse()
        buf = self.dbus.customized()
        fd = open(filename, 'w')
        fd.write(buf)
        fd.close()
        self.ready_mouse()

    def import_config(self, filename):
        fd = open(filename, "r")
        buf = fd.read()
        fd.close()
        self.wait_mouse()
        try:
            self.dbus.semanage(buf)
        except OSError:
            pass
        self.ready_mouse()

    def init_dictionary(self, dic, app, ipage, operation, p, q, ftype, mls, changed, old):
        if (app, ipage, operation) not in dic:
            dic[app, ipage, operation] = {}
        if (p, q) not in dic[app, ipage, operation]:
            dic[app, ipage, operation][p, q] = {'type': ftype, 'mls': mls, 'changed': changed, 'old': old}

    def translate_bool(self, b):
        b = b.split('-')[1]
        if b == '0':
            return False
        if b == '1':
            return True

    def relabel_on_reboot(self, *args):
        active = self.relabel_button.get_active()
        exists = os.path.exists("/.autorelabel")

        if active and exists:
            return
        if not active and not exists:
            return
        try:
            self.dbus.relabel_on_boot(active)
        except dbus.exceptions.DBusException as e:
            self.error(e)

    def closewindow(self, window, *args):
        window.hide()
        self.recursive_path_toggle.set_active(False)
        self.window.set_sensitive(True)
        if self.moreTypes_window_files == window:
            self.show_popup(self.files_popup_window)
            if self.combo_get_active_text(self.files_type_combobox) == _('More...'):
                self.files_type_combobox.set_active(0)
        if self.error_check_window == window:
            if self.files_add:
                self.show_popup(self.files_popup_window)
            elif self.network_add:
                self.show_popup(self.network_popup_window)
        if self.files_mls_label.get_visible() or self.network_mls_label.get_visible():
            self.advanced_text_files.set_visible(True)
            self.files_mls_label.set_visible(False)
            self.files_mls_entry.set_visible(False)
            self.advanced_text_network.set_visible(True)
            self.network_mls_label.set_visible(False)
            self.network_mls_entry.set_visible(False)
        if self.main_advanced_label.get_text() == ADVANCED_SEARCH_LABEL[1]:
            self.main_advanced_label.set_text(ADVANCED_SEARCH_LABEL[0])
        return True

    def wait_mouse(self):
        self.window.get_window().set_cursor(self.busy_cursor)
        self.idle_func()

    def ready_mouse(self):
        self.window.get_window().set_cursor(self.ready_cursor)
        self.idle_func()

    def verify(self, message, title=""):
        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO,
                                Gtk.ButtonsType.YES_NO,
                                message)
        dlg.set_title(title)
        dlg.set_position(Gtk.WindowPosition.MOUSE)
        dlg.show_all()
        rc = dlg.run()
        dlg.destroy()
        return rc

    def error(self, message):
        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR,
                                Gtk.ButtonsType.CLOSE,
                                message)
        dlg.set_position(Gtk.WindowPosition.MOUSE)
        dlg.show_all()
        dlg.run()
        dlg.destroy()

    def enabled_changed(self, radio):
        if not radio.get_active():
            return
        label = radio.get_label()
        if label == 'Disabled' and self.enforce_mode != DISABLED:
            if self.verify(_("Changing to SELinux disabled requires a reboot.  It is not recommended.  If you later decide to turn SELinux back on, the system will be required to relabel.  If you just want to see if SELinux is causing a problem on your system, you can go to permissive mode which will only log errors and not enforce SELinux policy.  Permissive mode does not require a reboot.  Do you wish to continue?")) == Gtk.ResponseType.NO:
                self.enforce_button.set_active(True)

        if label != 'Disabled' and self.enforce_mode == DISABLED:
            if self.verify(_("Changing to SELinux enabled will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system.  Do you wish to continue?")) == Gtk.ResponseType.NO:
                self.enforce_button.set_active(True)
        self.enforce_button = radio

    def clear_filters(self, *args):
        self.filter_entry.set_text('')
        self.show_modified_only.set_active(False)

    def unconfined_toggle(self, *args):
        if not self.finish_init:
            return
        self.wait_mouse()
        if self.enable_unconfined_button.get_active():
            self.dbus.semanage("module -e unconfined")
        else:
            self.dbus.semanage("module -d unconfined")
        self.ready_mouse()

    def permissive_toggle(self, *args):
        if not self.finish_init:
            return
        self.wait_mouse()
        if self.enable_permissive_button.get_active():
            self.dbus.semanage("module -e permissivedomains")
        else:
            self.dbus.semanage("module -d permissivedomains")
        self.ready_mouse()

    def confirmation_close(self, button, *args):
        if len(self.update_treestore) > 0:
            if self.verify(_("You are attempting to close the application without applying your changes.\n    *    To apply changes you have made during this session, click No and click Update.\n    *    To leave the application without applying your changes, click Yes.  All changes that you have made during this session will be lost."), _("Loss of data Dialog")) == Gtk.ResponseType.NO:
                return True
        self.quit()

    def quit(self, *args):
        sys.exit(0)

if __name__ == '__main__':
    start = SELinuxGui()
