## fcontextPage.py - show selinux mappings
## Copyright (C) 2006 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 gtk
import gtk.glade
import os
import gobject
import seobject
import commands
from semanagePage import *

SPEC_COL = 0
TYPE_COL = 1
FTYPE_COL = 2


class context:

    def __init__(self, scontext):
        self.scontext = scontext
        con = scontext.split(":")
        self.type = con[0]
        if len(con) > 1:
            self.mls = con[1]
        else:
            self.mls = "s0"

    def __str__(self):
        return self.scontext

##
## 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 fcontextPage(semanagePage):

    def __init__(self, xml):
        semanagePage.__init__(self, xml, "fcontext", _("File Labeling"))
        self.fcontextFilter = xml.get_widget("fcontextFilterEntry")
        self.fcontextFilter.connect("focus_out_event", self.filter_changed)
        self.fcontextFilter.connect("activate", self.filter_changed)

        self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
        self.view = xml.get_widget("fcontextView")
        self.view.set_model(self.store)
        self.view.set_search_equal_func(self.search)

        col = gtk.TreeViewColumn(_("File\nSpecification"), gtk.CellRendererText(), text=SPEC_COL)
        col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        col.set_fixed_width(250)

        col.set_sort_column_id(SPEC_COL)
        col.set_resizable(True)
        self.view.append_column(col)
        col = gtk.TreeViewColumn(_("Selinux\nFile Type"), gtk.CellRendererText(), text=TYPE_COL)

        col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        col.set_fixed_width(250)
        col.set_sort_column_id(TYPE_COL)
        col.set_resizable(True)
        self.view.append_column(col)
        col = gtk.TreeViewColumn(_("File\nType"), gtk.CellRendererText(), text=2)
        col.set_sort_column_id(FTYPE_COL)
        col.set_resizable(True)
        self.view.append_column(col)

        self.store.set_sort_column_id(SPEC_COL, gtk.SORT_ASCENDING)
        self.load()
        self.fcontextEntry = xml.get_widget("fcontextEntry")
        self.fcontextFileTypeCombo = xml.get_widget("fcontextFileTypeCombo")
        liststore = self.fcontextFileTypeCombo.get_model()
        for k in seobject.file_types:
            if len(k) > 0 and k[0] != '-':
                iter = liststore.append()
                liststore.set_value(iter, 0, k)
        iter = liststore.get_iter_first()
        self.fcontextFileTypeCombo.set_active_iter(iter)
        self.fcontextTypeEntry = xml.get_widget("fcontextTypeEntry")
        self.fcontextMLSEntry = xml.get_widget("fcontextMLSEntry")

    def match(self, fcon_dict, k, filter):
        try:
            f = filter.lower()
            for con in k:
                k = con.lower()
                if k.find(f) >= 0:
                    return True
            for con in fcon_dict[k]:
                k = con.lower()
                if k.find(f) >= 0:
                    return True
        except:
            pass
        return False

    def load(self, filter=""):
        self.filter = filter
        self.fcontext = seobject.fcontextRecords()
        self.store.clear()
        fcon_dict = self.fcontext.get_all(self.local)
        keys = fcon_dict.keys()
        keys.sort()
        for k in keys:
            if not self.match(fcon_dict, k, filter):
                continue
            iter = self.store.append()
            self.store.set_value(iter, SPEC_COL, k[0])
            self.store.set_value(iter, FTYPE_COL, k[1])
            if fcon_dict[k]:
                rec = "%s:%s" % (fcon_dict[k][2], seobject.translate(fcon_dict[k][3], False))
            else:
                rec = "<<None>>"
            self.store.set_value(iter, TYPE_COL, rec)
        self.view.get_selection().select_path((0,))

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

    def dialogInit(self):
        store, iter = self.view.get_selection().get_selected()
        self.fcontextEntry.set_text(store.get_value(iter, SPEC_COL))
        self.fcontextEntry.set_sensitive(False)
        scontext = store.get_value(iter, TYPE_COL)
        scon = context(scontext)
        self.fcontextTypeEntry.set_text(scon.type)
        self.fcontextMLSEntry.set_text(scon.mls)
        type = store.get_value(iter, FTYPE_COL)
        liststore = self.fcontextFileTypeCombo.get_model()
        iter = liststore.get_iter_first()
        while iter != None and liststore.get_value(iter, 0) != type:
            iter = liststore.iter_next(iter)
        if iter != None:
            self.fcontextFileTypeCombo.set_active_iter(iter)
        self.fcontextFileTypeCombo.set_sensitive(False)

    def dialogClear(self):
        self.fcontextEntry.set_text("")
        self.fcontextEntry.set_sensitive(True)
        self.fcontextFileTypeCombo.set_sensitive(True)
        self.fcontextTypeEntry.set_text("")
        self.fcontextMLSEntry.set_text("s0")

    def delete(self):
        store, iter = self.view.get_selection().get_selected()
        try:
            fspec = store.get_value(iter, SPEC_COL)
            ftype = store.get_value(iter, FTYPE_COL)
            self.wait()
            (rc, out) = commands.getstatusoutput("semanage fcontext -d -f '%s' '%s'" % (ftype, fspec))
            self.ready()

            if rc != 0:
                return self.error(out)
            store.remove(iter)
            self.view.get_selection().select_path((0,))
        except ValueError, e:
            self.error(e.args[0])

    def add(self):
        ftype = ["", "--", "-d", "-c", "-b", "-s", "-l", "-p"]
        fspec = self.fcontextEntry.get_text().strip()
        type = self.fcontextTypeEntry.get_text().strip()
        mls = self.fcontextMLSEntry.get_text().strip()
        list_model = self.fcontextFileTypeCombo.get_model()
        active = self.fcontextFileTypeCombo.get_active()
        self.wait()
        (rc, out) = commands.getstatusoutput("semanage fcontext -a -t %s -r %s -f '%s' '%s'" % (type, mls, ftype[active], fspec))
        self.ready()
        if rc != 0:
            self.error(out)
            return False

        iter = self.store.append()
        self.store.set_value(iter, SPEC_COL, fspec)
        self.store.set_value(iter, FTYPE_COL, ftype)
        self.store.set_value(iter, TYPE_COL, "%s:%s" % (type, mls))

    def modify(self):
        fspec = self.fcontextEntry.get_text().strip()
        type = self.fcontextTypeEntry.get_text().strip()
        mls = self.fcontextMLSEntry.get_text().strip()
        list_model = self.fcontextFileTypeCombo.get_model()
        iter = self.fcontextFileTypeCombo.get_active_iter()
        ftype = list_model.get_value(iter, 0)
        self.wait()
        (rc, out) = commands.getstatusoutput("semanage fcontext -m -t %s -r %s -f '%s' '%s'" % (type, mls, ftype, fspec))
        self.ready()
        if rc != 0:
            self.error(out)
            return False

        store, iter = self.view.get_selection().get_selected()
        self.store.set_value(iter, SPEC_COL, fspec)
        self.store.set_value(iter, FTYPE_COL, ftype)
        self.store.set_value(iter, TYPE_COL, "%s:%s" % (type, mls))
