diff options
Diffstat (limited to 'apol/open_policy_dialog.tcl')
-rw-r--r-- | apol/open_policy_dialog.tcl | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/apol/open_policy_dialog.tcl b/apol/open_policy_dialog.tcl new file mode 100644 index 0000000..217ca85 --- /dev/null +++ b/apol/open_policy_dialog.tcl @@ -0,0 +1,388 @@ +# Copyright (C) 2007 Tresys Technology, LLC +# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace eval Apol_Open_Policy_Dialog { + variable dialog {} + variable widgets + variable vars +} + +# Create a dialog box to allow the user to select a policy path. +proc Apol_Open_Policy_Dialog::getPolicyPath {defaultPath} { + variable dialog + variable vars + + array unset vars + _create_dialog . + + set vars(path_type) "monolithic" + set vars(primary_file) {} + set vars(last_module) {} + set vars(mod_names) {} + set vars(mod_vers) {} + set vars(mod_paths) {} + + if {$defaultPath != {}} { + foreach {path_type primary modules} [policy_path_to_list $defaultPath] {break} + set vars(path_type) $path_type + if {[set vars(primary_file) $primary] != {}} { + $dialog itemconfigure 0 -state normal + } + set vars(last_module) $vars(primary_file) + foreach m $modules { + if {[catch {getModuleInfo $m} info]} { + tk_messageBox -icon error -type ok -title "Open Module" -message $info -detail "Module file $m" -parent [$dialog getframe] + } else { + foreach {name vers type} $info {break} + lappend vars(mod_names) $name + lappend vars(mod_vers) $vers + lappend vars(mod_paths) $m + set vars(last_module) $m + } + } + } + # force a recomputation of button sizes (bug in ButtonBox) + $dialog.bbox _redraw + $dialog draw + destroy $dialog +} + +########## private functions below ########## + +proc Apol_Open_Policy_Dialog::_create_dialog {parent} { + variable dialog + variable widgets + variable vars + + destroy $dialog + set dialog [Dialog .open_policy_dialog -modal local -parent $parent \ + -cancel 1 \ + -separator 1 -homogeneous 1 -title "Open Policy"] + + set f [$dialog getframe] + + set policy_type_f [frame $f.policy_type] + pack $policy_type_f -padx 4 -pady 4 -expand 0 -anchor w + set l [label $policy_type_f.l -text "Policy Type:"] + set mono_cb [radiobutton $policy_type_f.mono -text "Monolithic policy" \ + -value monolithic \ + -variable Apol_Open_Policy_Dialog::vars(path_type)] + set mod_cb [radiobutton $policy_type_f.mod -text "Modular policy" \ + -value modular \ + -variable Apol_Open_Policy_Dialog::vars(path_type)] + pack $l -anchor w + pack $mono_cb $mod_cb -anchor w -padx 8 + + set primary_f [frame $f.primary] + pack $primary_f -padx 4 -pady 8 -expand 0 -fill x + set widgets(main_label) [label $primary_f.l -text "Policy Filename:"] + pack $widgets(main_label) -anchor w + frame $primary_f.f + pack $primary_f.f -expand 1 -fill x + set e [entry $primary_f.f.e -width 32 -bg white \ + -textvariable Apol_Open_Policy_Dialog::vars(primary_file) \ + -validate key \ + -vcmd [list Apol_Open_Policy_Dialog::_validateEntryKey %P]] + bind $e <Key-Return> Apol_Open_Policy_Dialog::tryOpenPolicy + set b [button $primary_f.f.b -text "Browse" \ + -command Apol_Open_Policy_Dialog::browsePrimary] + pack $e -side left -expand 1 -fill x -padx 4 + pack $b -side right -expand 0 -padx 4 + + set modules_f [frame $f.modules] + pack $modules_f -pady 4 -padx 4 -expand 1 -fill both + set mod_list_f [frame $modules_f.mods -relief sunken] + pack $mod_list_f -side left -expand 1 -fill both -padx 4 + set mlabel [label $mod_list_f.ml -text "Module:"] + set vlabel [label $mod_list_f.vl -text "Version:"] + set plabel [label $mod_list_f.pl -text "Path:"] + grid $mlabel $vlabel $plabel x -sticky w + set dis_bg [$mlabel cget -bg] + set ml [listbox $mod_list_f.mods -height 6 -width 10 \ + -listvariable Apol_Open_Policy_Dialog::vars(mod_names)] + set vl [listbox $mod_list_f.vers -height 6 -width 4 \ + -listvariable Apol_Open_Policy_Dialog::vars(mod_vers)] + set pl [listbox $mod_list_f.paths -height 6 -width 24 \ + -listvariable Apol_Open_Policy_Dialog::vars(mod_paths)] + set sb [scrollbar $mod_list_f.sb -orient vertical \ + -command [list Apol_Open_Policy_Dialog::multiscroll yview]] + grid $ml $vl $pl $sb -sticky nsew + set widgets(bb) [ButtonBox $modules_f.bb -homogeneous 1 -orient vertical -pady 2] + $widgets(bb) add -text "Add" -command Apol_Open_Policy_Dialog::browseModule + $widgets(bb) add -text "Remove" -command Apol_Open_Policy_Dialog::removeModule -state disabled + $widgets(bb) add -text "Import" -command Apol_Open_Policy_Dialog::importList + $widgets(bb) add -text "Export" -command Apol_Open_Policy_Dialog::exportList -state disabled + pack $widgets(bb) -side right -expand 0 -anchor n -padx 4 -pady 10 + + set widgets(listboxes) [list $ml $vl $pl] + set widgets(scrollbar) $sb + foreach lb $widgets(listboxes) { + $lb configure -yscrollcommand Apol_Open_Policy_Dialog::multiyview \ + -relief groove -bg white -exportselection 0 + bind $lb <<ListboxSelect>> \ + [list Apol_Open_Policy_Dialog::multiselect $lb] + } + + trace add variable Apol_Open_Policy_Dialog::vars(path_type) write \ + [list Apol_Open_Policy_Dialog::togglePathType \ + [list $mlabel $vlabel $plabel] $dis_bg] + $dialog add -text "OK" -command Apol_Open_Policy_Dialog::tryOpenPolicy \ + -state disabled + $dialog add -text "Cancel" +} + +proc Apol_Open_Policy_Dialog::_validateEntryKey {newvalue} { + variable vars + variable dialog + variable widgets + if {$newvalue == {}} { + $dialog itemconfigure 0 -state disabled + $widgets(bb) itemconfigure 3 -state disabled + } else { + $dialog itemconfigure 0 -state normal + if {$vars(path_type) == "modular"} { + $widgets(bb) itemconfigure 3 -state normal + } else { + $widgets(bb) itemconfigure 3 -state disabled + } + } + return 1 +} + +proc Apol_Open_Policy_Dialog::togglePathType {labels disabled_bg name1 name2 op} { + variable vars + variable widgets + if {$vars(path_type) == "modular"} { + set state normal + set bg white + $widgets(main_label) configure -text "Base Filename:" + } else { + set state disabled + set bg $disabled_bg + $widgets(main_label) configure -text "Policy Filename:" + } + foreach w $labels { + $w configure -state $state + } + foreach w $widgets(listboxes) { + $w configure -state $state -bg $bg + } + $widgets(bb) configure -state $state + if {$state == "normal" && [[lindex $widgets(listboxes) 0] curselection] > 0} { + $widgets(bb) itemconfigure 1 -state normal + } else { + $widgets(bb) itemconfigure 1 -state disabled + } + if {$state == "normal" && $vars(primary_file) != {}} { + $widgets(bb) itemconfigure 3 -state normal + } else { + $widgets(bb) itemconfigure 3 -state disabled + } +} + +proc Apol_Open_Policy_Dialog::browsePrimary {} { + variable vars + variable dialog + .open_policy_dialog.frame.primary.f.b configure -state disabled + if {$vars(path_type) == "monolithic"} { + set title "Open Monolithic Policy" + set initDirName {} + } else { + set title "Open Modular Policy" + if {$vars(primary_file) != {} } { + set initDirName [file dirname $vars(primary_file)] + } else { + set initDirName [file dirname $vars(last_module)] + } + } + set f [tk_getOpenFile -initialdir $initDirName \ + -initialfile $vars(primary_file) -parent $dialog -title $title] + if {$f != {}} { + set vars(primary_file) $f + $dialog itemconfigure 0 -state normal + } + .open_policy_dialog.frame.primary.f.b configure -state normal +} + +proc Apol_Open_Policy_Dialog::browseModule {} { + variable vars + variable dialog + + if {$vars(last_module) != {} } { + set initDirName [file dirname $vars(last_module)] + } else { + set initDirName [file dirname $vars(primary_file)] + } + set paths [tk_getOpenFile -initialdir $initDirName \ + -initialfile $vars(last_module) -parent $dialog \ + -title "Open Module" -multiple 1] + if {$paths == {}} { + return + } + foreach f $paths { + # tk_getOpenFile returns "initialfile" as a selected file, so skip it. + if { $f != $vars(last_module) } { + addModule $f + } + } +} + +proc Apol_Open_Policy_Dialog::addModule {f} { + variable vars + variable widgets + if {[lsearch $vars(mod_paths) $f] >= 0} { + tk_messageBox -icon error -type ok -title "Open Module" -message "Module $f was already added." -parent .open_policy_dialog + return + } + if {[catch {getModuleInfo $f} info]} { + tk_messageBox -icon error -type ok -title "Open Module" -message $info -detail "Module file $f" -parent .open_policy_dialog + } else { + foreach {name vers type} $info {break} + if {$type == 1} { + if {$vars(primary_file) != {}} { + if {$vars(primary_file) != $f} { + tk_messageBox -icon error -type ok -title "Open Module" -message "Base already set" -detail "Current $vars(primary_file)\n\nNew file $f\n\nIgnoring new file." -parent .open_policy_dialog + } + return + } + set vars(primary_file) $f + return + } + set vars(mod_names) [lsort [concat $vars(mod_names) $name]] + set i [lsearch $vars(mod_names) $name] + set vars(mod_vers) [linsert $vars(mod_vers) $i $vers] + set vars(mod_paths) [linsert $vars(mod_paths) $i $f] + foreach lb $widgets(listboxes) { + $lb selection clear 0 end + $lb selection set $i + } + [lindex $widgets(listboxes) 0] see $i + set vars(last_module) $f + $widgets(bb) itemconfigure 1 -state normal + } +} + +proc Apol_Open_Policy_Dialog::removeModule {} { + variable widgets + set i [[lindex $widgets(listboxes) 0] curselection] + if {[llength $i] > 0} { + foreach lb $widgets(listboxes) { + $lb delete [lindex $i 0] + } + } + $widgets(bb) itemconfigure 1 -state disabled +} + +proc Apol_Open_Policy_Dialog::importList {} { + variable vars + variable dialog + variable widgets + set f [tk_getOpenFile -initialdir [file dirname $vars(primary_file)] \ + -parent $dialog -title "Import Policy List"] + if {$f == {}} { + return + } + if {[catch {new_apol_policy_path_t $f} ppath]} { + tk_messageBox -icon error -type ok -title "Import Policy List" \ + -message "Error importing policy list $f: $ppath" + return + } + foreach lb $widgets(listboxes) { + $lb delete 0 end + } + foreach {path_type primary modules} [policy_path_to_list $ppath] {break} + set vars(path_type) $path_type + if {[set vars(primary_file) $primary] != {}} { + $dialog itemconfigure 0 -state normal + } + set vars(last_module) $f + foreach m $modules { + addModule $m + } + _validateEntryKey $vars(primary_file) + $ppath -acquire + $ppath -delete +} + +proc Apol_Open_Policy_Dialog::exportList {} { + variable vars + variable dialog + set f [tk_getSaveFile -parent $dialog -title "Export Policy List"] + if {$f == {}} { + return + } + set ppath [list_to_policy_path $vars(path_type) $vars(primary_file) $vars(mod_paths)] + if {[catch {$ppath to_file $f} err]} { + tk_messageBox -icon error -type ok -title "Export Policy List" \ + -message "Error exporting policy list $f: $err" + } +} + +proc Apol_Open_Policy_Dialog::multiscroll {args} { + variable widgets + foreach lb $widgets(listboxes) { + eval $lb $args + } +} + +proc Apol_Open_Policy_Dialog::multiselect {lb} { + variable widgets + set sellist [$lb curselection] + set enable_remove 0 + foreach lb $widgets(listboxes) { + $lb selection clear 0 end + foreach item $sellist { + $lb selection set $item + set enable_remove 1 + } + } + if {$enable_remove} { + $widgets(bb) itemconfigure 1 -state normal + } +} + +proc Apol_Open_Policy_Dialog::multiyview {args} { + variable widgets + eval $widgets(scrollbar) set $args + multiscroll yview moveto [lindex $args 0] +} + + +# Generate a policy path and try to open the given policy. Upon +# success end the dialog and return that path. Otherwise do not close +# the dialog. +proc Apol_Open_Policy_Dialog::tryOpenPolicy {} { + variable dialog + variable vars + .open_policy_dialog.bbox.b0 configure -state disabled + if {[string trim $vars(primary_file)] != {}} { + set ppath [list_to_policy_path $vars(path_type) $vars(primary_file) $vars(mod_paths)] + if {[ApolTop::openPolicyPath $ppath] == 0} { + $dialog enddialog {} + } + } + .open_policy_dialog.bbox.b0 configure -state normal +} + +# Retrieve information about a policy module file, either source or +# binary, from disk. This will be a 3-ple of module name, version and type. +# The policy module will be closed afterwards. +proc Apol_Open_Policy_Dialog::getModuleInfo {f} { + set mod [new_qpol_module_t $f] + set retval [list [$mod get_name] [$mod get_version] [$mod get_type]] + $mod -acquire + $mod -delete + return $retval +} |