#!/usr/bin/python3 -Es
#
# 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
#
#

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 time
import os
import re
import gettext
import unicodedata

PROGNAME = "policycoreutils"
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
try:
    gettext.install(PROGNAME,
                    unicode=True,
                    codeset='utf-8')
except TypeError:
    # Failover to python3 install
    gettext.install(PROGNAME,
                    codeset='utf-8')
except IOError:
    import builtins
    builtins.__dict__['_'] = str

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")]

import distutils.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 = distutils.sysconfig.get_python_lib(plat_specific=True) + "/sepolicy/"
        glade_file = self.code_path + "sepolicy.glade"
        builder.add_from_file(glade_file)
        self.outer_notebook = builder.g
et_object("outer_notebook")
        self.window = builder.get_object("SELinux_window")
        self.main_selection_window = builder.get_object("Ma
in_selection_menu")
        self.main_advanced_label = builder.get_object("main_advanced_label")
        self.popup = 0
        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.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")