#
# booleansPage.py - GUI for Booleans page in system-config-securitylevel
#
# Dan Walsh <dwalsh@redhat.com>
#
# Copyright 2006, 2007 Red Hat, Inc.
#
# 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
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
import string
import gtk
import gtk.glade
import os
import gobject
import sys
import tempfile
import seobject
import semanagePage

INSTALLPATH = '/usr/share/system-config-selinux'
sys.path.append(INSTALLPATH)

import commands
ENFORCING = 0
PERMISSIVE = 1
DISABLED = 2

##
## I18N
##
PROGNAME = "policycoreutils"

import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
try:
    gettext.install(PROGNAME,
                    localedir="/usr/share/locale",
                    unicode=False,
                    codeset='utf-8')
except IOError:
    import __builtin__
    __builtin__.__dict__['_'] = unicode

from glob import fnmatch


class Modifier:

    def __init__(self, name, on, save):
        self.on = on
        self.name = name
        self.save = save

    def set(self, value):
        self.on = value
        self.save = True

    def isOn(self):
        return self.on


class Boolean(Modifier):

    def __init__(self, name, val, save=False):
        Modifier.__init__(self, name, val, save)

ACTIVE = 0
MODULE = 1
DESC = 2
BOOLEAN = 3


class booleansPage:

    def __init__(self, xml, doDebug=None):
        self.xml = xml
        self.window = self.xml.get_widget("mainWindow").get_root_window()
        self.local = False
        self.types = []
        self.selinuxsupport = True
        self.typechanged = False
        self.doDebug = doDebug
        self.busy_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
        self.ready_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)

        # Bring in widgets from glade file.
        self.typeHBox = xml.get_widget("typeHBox")
        self.booleanSW = xml.get_widget("booleanSW")
        self.booleansFilter = xml.get_widget("booleansFilter")
        self.booleansFilter.connect("focus_out_event", self.filter_changed)
        self.booleansFilter.connect("activate", self.filter_changed)

        self.booleansView = xml.get_widget("booleansView")
        self.typeLabel = xml.get_widget("typeLabel")
        self.modifySeparator = xml.get_widget("modifySeparator")

        self.revertButton = xml.get_widget("booleanRevertButton")
        self.revertButton.set_sensitive(self.local)
        self.revertButton.connect("clicked", self.on_revert_clicked)
        listStore = gtk.ListStore(gobject.TYPE_STRING)
        cell = gtk.CellRendererText()

        self.store = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
        self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
        self.booleansView.set_model(self.store)

        checkbox = gtk.CellRendererToggle()
        checkbox.connect("toggled", self.boolean_toggled)
        col = gtk.TreeViewColumn('Active', checkbox, active=ACTIVE)
        col.set_clickable(True)
        col.set_sort_column_id(ACTIVE)
        self.booleansView.append_column(col)

        col = gtk.TreeViewColumn("Module", gtk.CellRendererText(), text=MODULE)
        col.set_sort_column_id(MODULE)
        col.set_resizable(True)
        self.booleansView.append_column(col)

        col = gtk.TreeViewColumn("Description", gtk.CellRendererText(), text=DESC)
        col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        col.set_fixed_width(400)
        col.set_sort_column_id(DESC)
        col.set_resizable(True)
        self.booleansView.append_column(col)

        col = gtk.TreeViewColumn("Name", gtk.CellRendererText(), text=BOOLEAN)
        col.set_sort_column_id(BOOLEAN)
        col.set_resizable(True)
        self.booleansView.set_search_equal_func(self.__search)
        self.booleansView.append_column(col)
        self.filter = ""
        self.load(self.filter)

    def error(self, message):
        dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR,
                                gtk.BUTTONS_CLOSE,
                                message)
        dlg.set_position(gtk.WIN_POS_MOUSE)
        dlg.show_all()
        dlg.run()
        dlg.destroy()

    def __search(self, model, col, key, i):
        sort_col = self.store.get_sort_column_id()[0]
        if sort_col > 0:
            val = model.get_value(i, sort_col)
            if val.lower().startswith(key.lower()):
                return False
        return True

    def wait(self):
        self.window.set_cursor(self.busy_cursor)
        semanagePage.idle_func()

    def ready(self):
        self.window.set_cursor(self.ready_cursor)
        semanagePage.idle_func()

    def deleteDialog(self):
        store, iter = self.booleansView.get_selection().get_selected()
        if iter == None:
            return
        boolean = store.get_value(iter, BOOLEAN)
        # change cursor
        if boolean == None:
            return
        try:
            self.wait()
            (rc, out) = commands.getstatusoutput("semanage boolean -d %s" % boolean)

            self.ready()
            if rc != 0:
                return self.error(out)
            self.load(self.filter)
        except ValueError, e:
            self.error(e.args[0])

    def filter_changed(self, *arg):
        filter = arg[0].get_text()
        if filter != self.filter:
            self.load(filter)
            self.filter = filter

    def use_menus(self):
        return False

    def get_description(self):
        return _("Boolean")

    def match(self, key, filter=""):
        try:
            f = filter.lower()
            cat = self.booleans.get_category(key).lower()
            val = self.booleans.get_desc(key).lower()
            k = key.lower()
            return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0
        except:
            return False

    def load(self, filter=None):
        self.store.clear()
        self.booleans = seobject.booleanRecords()
        booleansList = self.booleans.get_all(self.local)
        for name in booleansList:
            rec = booleansList[name]
            if self.match(name, filter):
                iter = self.store.append()
                self.store.set_value(iter, ACTIVE, rec[2] == 1)
                self.store.set_value(iter, MODULE, self.booleans.get_category(name))
                self.store.set_value(iter, DESC, self.booleans.get_desc(name))
                self.store.set_value(iter, BOOLEAN, name)

    def boolean_toggled(self, widget, row):
        iter = self.store.get_iter(row)
        val = self.store.get_value(iter, ACTIVE)
        key = self.store.get_value(iter, BOOLEAN)
        self.store.set_value(iter, ACTIVE, not val)
        self.wait()
        setsebool = "/usr/sbin/setsebool -P %s %d" % (key, not val)
        rc, out = commands.getstatusoutput(setsebool)
        if rc != 0:
            self.error(out)
        self.load(self.filter)
        self.ready()

    def on_revert_clicked(self, button):
        self.wait()
        setsebool = "semanage boolean --deleteall"
        commands.getstatusoutput(setsebool)
        self.load(self.filter)
        self.ready()

    def on_local_clicked(self, button):
        self.local = not self.local
        self.revertButton.set_sensitive(self.local)

        if self.local:
            button.set_label(_("all"))
        else:
            button.set_label(_("Customized"))

        self.load(self.filter)
        return True
