1#
2# booleansPage.py - GUI for Booleans page in system-config-securitylevel
3#
4# Dan Walsh <dwalsh@redhat.com>
5#
6# Copyright 2006, 2007 Red Hat, Inc.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20#
21import string
22import gtk
23import gtk.glade
24import os
25import gobject
26import sys
27import tempfile
28import seobject
29import semanagePage
30
31INSTALLPATH='/usr/share/system-config-selinux'
32sys.path.append(INSTALLPATH)
33
34import commands
35ENFORCING=0
36PERMISSIVE=1
37DISABLED=2
38
39##
40## I18N
41##
42PROGNAME="policycoreutils"
43
44import gettext
45gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
46gettext.textdomain(PROGNAME)
47try:
48    gettext.install(PROGNAME,
49                    localedir="/usr/share/locale",
50                    unicode=False,
51                    codeset = 'utf-8')
52except IOError:
53    import __builtin__
54    __builtin__.__dict__['_'] = unicode
55
56from glob import fnmatch
57
58class Modifier:
59    def __init__(self,name, on, save):
60        self.on=on
61        self.name=name
62        self.save=save
63
64    def set(self,value):
65        self.on=value
66        self.save=True
67
68    def isOn(self):
69        return self.on
70
71class Boolean(Modifier):
72    def __init__(self,name, val, save=False):
73        Modifier.__init__(self,name, val, save)
74
75ACTIVE = 0
76MODULE = 1
77DESC = 2
78BOOLEAN = 3
79
80class booleansPage:
81    def __init__(self, xml, doDebug=None):
82        self.xml = xml
83        self.window = self.xml.get_widget("mainWindow").get_root_window()
84        self.local = False
85        self.types=[]
86        self.selinuxsupport = True
87        self.typechanged = False
88        self.doDebug = doDebug
89        self.busy_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
90        self.ready_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
91
92        # Bring in widgets from glade file.
93        self.typeHBox = xml.get_widget("typeHBox")
94        self.booleanSW = xml.get_widget("booleanSW")
95        self.booleansFilter = xml.get_widget("booleansFilter")
96        self.booleansFilter.connect("focus_out_event", self.filter_changed)
97        self.booleansFilter.connect("activate", self.filter_changed)
98
99        self.booleansView = xml.get_widget("booleansView")
100        self.typeLabel = xml.get_widget("typeLabel")
101        self.modifySeparator = xml.get_widget("modifySeparator")
102
103        self.revertButton = xml.get_widget("booleanRevertButton")
104        self.revertButton.set_sensitive(self.local)
105        self.revertButton.connect("clicked", self.on_revert_clicked)
106        listStore = gtk.ListStore(gobject.TYPE_STRING)
107        cell = gtk.CellRendererText()
108
109        self.store = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
110        self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
111        self.booleansView.set_model(self.store)
112
113        checkbox = gtk.CellRendererToggle()
114        checkbox.connect("toggled", self.boolean_toggled)
115        col = gtk.TreeViewColumn('Active', checkbox, active = ACTIVE)
116        col.set_clickable(True)
117        col.set_sort_column_id(ACTIVE)
118        self.booleansView.append_column(col)
119
120        col = gtk.TreeViewColumn("Module", gtk.CellRendererText(), text=MODULE)
121        col.set_sort_column_id(MODULE)
122        col.set_resizable(True)
123        self.booleansView.append_column(col)
124
125        col = gtk.TreeViewColumn("Description", gtk.CellRendererText(), text=DESC)
126	col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
127        col.set_fixed_width(400)
128        col.set_sort_column_id(DESC)
129        col.set_resizable(True)
130        self.booleansView.append_column(col)
131
132        col = gtk.TreeViewColumn("Name", gtk.CellRendererText(), text=BOOLEAN)
133        col.set_sort_column_id(BOOLEAN)
134        col.set_resizable(True)
135        self.booleansView.set_search_equal_func(self.__search)
136        self.booleansView.append_column(col)
137        self.filter=""
138        self.load(self.filter)
139
140    def error(self, message):
141        dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR,
142                                gtk.BUTTONS_CLOSE,
143                                message)
144        dlg.set_position(gtk.WIN_POS_MOUSE)
145        dlg.show_all()
146        dlg.run()
147        dlg.destroy()
148
149    def __search(self, model, col, key, i):
150        sort_col = self.store.get_sort_column_id()[0]
151        if sort_col > 0:
152            val = model.get_value(i, sort_col)
153            if val.lower().startswith(key.lower()):
154                return False
155        return True
156
157    def wait(self):
158        self.window.set_cursor(self.busy_cursor)
159        semanagePage.idle_func()
160
161    def ready(self):
162        self.window.set_cursor(self.ready_cursor)
163        semanagePage.idle_func()
164
165    def deleteDialog(self):
166        store, iter = self.booleansView.get_selection().get_selected()
167        if iter == None:
168            return
169        boolean = store.get_value(iter, BOOLEAN)
170        # change cursor
171        if boolean == None:
172            return
173        try:
174            self.wait()
175            (rc, out) = commands.getstatusoutput("semanage boolean -d %s" % boolean)
176
177            self.ready()
178            if rc != 0:
179                return self.error(out)
180            self.load(self.filter)
181        except ValueError, e:
182            self.error(e.args[0])
183
184    def filter_changed(self, *arg):
185        filter =  arg[0].get_text()
186        if filter != self.filter:
187            self.load(filter)
188            self.filter=filter
189
190    def use_menus(self):
191        return False
192
193    def get_description(self):
194        return _("Boolean")
195
196    def match(self,key, filter=""):
197        try:
198            f=filter.lower()
199            cat=self.booleans.get_category(key).lower()
200            val=self.booleans.get_desc(key).lower()
201            k=key.lower()
202            return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0
203        except:
204            return False
205
206
207    def load(self, filter=None):
208        self.store.clear()
209        self.booleans = seobject.booleanRecords()
210        booleansList = self.booleans.get_all(self.local)
211        for name in booleansList:
212            rec = booleansList[name]
213            if self.match(name, filter):
214                iter=self.store.append()
215                self.store.set_value(iter, ACTIVE, rec[2] == 1)
216                self.store.set_value(iter, MODULE, self.booleans.get_category(name))
217                self.store.set_value(iter, DESC, self.booleans.get_desc(name))
218                self.store.set_value(iter, BOOLEAN, name)
219
220    def boolean_toggled(self, widget, row):
221        iter = self.store.get_iter(row)
222        val = self.store.get_value(iter, ACTIVE)
223        key = self.store.get_value(iter, BOOLEAN)
224        self.store.set_value(iter, ACTIVE , not val)
225        self.wait()
226        setsebool="/usr/sbin/setsebool -P %s %d" % (key, not val)
227        rc,out = commands.getstatusoutput(setsebool)
228        if rc != 0:
229            self.error(out)
230        self.load(self.filter)
231        self.ready()
232
233    def on_revert_clicked(self, button):
234        self.wait()
235        setsebool="semanage boolean --deleteall"
236        commands.getstatusoutput(setsebool)
237        self.load(self.filter)
238        self.ready()
239
240    def on_local_clicked(self, button):
241        self.local = not self.local
242        self.revertButton.set_sensitive(self.local)
243
244        if self.local:
245            button.set_label(_("all"))
246        else:
247            button.set_label(_("Customized"))
248
249        self.load(self.filter)
250        return True
251