## modulesPage.py - show selinux mappings
## Copyright (C) 2006-2009 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
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

## Author: Dan Walsh
import string
import gtk
import gtk.glade
import os
import commands
import gobject
import sys
import seobject
import selinux
from semanagePage import *
from subprocess import Popen, PIPE

##
## 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


class modulesPage(semanagePage):

    def __init__(self, xml):
        semanagePage.__init__(self, xml, "modules", _("Policy Module"))
        self.module_filter = xml.get_widget("modulesFilterEntry")
        self.module_filter.connect("focus_out_event", self.filter_changed)
        self.module_filter.connect("activate", self.filter_changed)
        self.audit_enabled = False

        self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
        self.view.set_model(self.store)
        self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
        col = gtk.TreeViewColumn(_("Module Name"), gtk.CellRendererText(), text=0)
        col.set_sort_column_id(0)
        col.set_resizable(True)
        self.view.append_column(col)
        self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
        col = gtk.TreeViewColumn(_("Version"), gtk.CellRendererText(), text=1)
        self.enable_audit_button = xml.get_widget("enableAuditButton")
        self.enable_audit_button.connect("clicked", self.enable_audit)
        self.new_button = xml.get_widget("newModuleButton")
        self.new_button.connect("clicked", self.new_module)
        col.set_sort_column_id(1)
        col.set_resizable(True)
        self.view.append_column(col)
        self.store.set_sort_func(1, self.sort_int, "")
        status, self.policy_type = selinux.selinux_getpolicytype()

        self.load()

    def sort_int(self, treemodel, iter1, iter2, user_data):
        try:
            p1 = int(treemodel.get_value(iter1, 1))
            p2 = int(treemodel.get_value(iter1, 1))
            if p1 > p2:
                return 1
            if p1 == p2:
                return 0
            return -1
        except:
            return 0

    def load(self, filter=""):
        self.filter = filter
        self.store.clear()
        try:
            fd = Popen("semodule -l", shell=True, stdout=PIPE).stdout
            l = fd.readlines()
            fd.close()
            for i in l:
                module, ver, newline = i.split('\t')
                if not (self.match(module, filter) or self.match(ver, filter)):
                    continue
                iter = self.store.append()
                self.store.set_value(iter, 0, module.strip())
                self.store.set_value(iter, 1, ver.strip())
        except:
            pass
        self.view.get_selection().select_path((0,))

    def new_module(self, args):
        try:
            Popen(["/usr/share/system-config-selinux/polgengui.py"])
        except ValueError, e:
            self.error(e.args[0])

    def delete(self):
        store, iter = self.view.get_selection().get_selected()
        module = store.get_value(iter, 0)
        try:
            self.wait()
            status, output = commands.getstatusoutput("semodule -r %s" % module)
            self.ready()
            if status != 0:
                self.error(output)
            else:
                store.remove(iter)
                self.view.get_selection().select_path((0,))

        except ValueError, e:
            self.error(e.args[0])

    def enable_audit(self, button):
        self.audit_enabled = not self.audit_enabled
        try:
            self.wait()
            if self.audit_enabled:
                status, output = commands.getstatusoutput("semodule -DB")
                button.set_label(_("Disable Audit"))
            else:
                status, output = commands.getstatusoutput("semodule -B")
                button.set_label(_("Enable Audit"))
            self.ready()

            if status != 0:
                self.error(output)

        except ValueError, e:
            self.error(e.args[0])

    def disable_audit(self, button):
        try:
            self.wait()
            status, output = commands.getstatusoutput("semodule -B")
            self.ready()
            if status != 0:
                self.error(output)

        except ValueError, e:
            self.error(e.args[0])

    def propertiesDialog(self):
        # Do nothing
        return

    def addDialog(self):
        dialog = gtk.FileChooserDialog(_("Load Policy Module"),
                                       None,
                                       gtk.FILE_CHOOSER_ACTION_OPEN,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)

        filter = gtk.FileFilter()
        filter.set_name("Policy Files")
        filter.add_pattern("*.pp")
        dialog.add_filter(filter)

        response = dialog.run()
        if response == gtk.RESPONSE_OK:
            self.add(dialog.get_filename())
        dialog.destroy()

    def add(self, file):
        try:
            self.wait()
            status, output = commands.getstatusoutput("semodule -i %s" % file)
            self.ready()
            if status != 0:
                self.error(output)
            else:
                self.load()

        except ValueError, e:
            self.error(e.args[0])
