summaryrefslogtreecommitdiffstats
path: root/perl-install/standalone/drakperm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/standalone/drakperm')
-rwxr-xr-xperl-install/standalone/drakperm786
1 files changed, 406 insertions, 380 deletions
diff --git a/perl-install/standalone/drakperm b/perl-install/standalone/drakperm
index a94d9d6b0..fa69be838 100755
--- a/perl-install/standalone/drakperm
+++ b/perl-install/standalone/drakperm
@@ -1,416 +1,442 @@
#!/usr/bin/perl
+use strict;
+use diagnostics;
use lib qw(/usr/lib/libDrakX);
use standalone;
use MDK::Common;
+use common;
+use mygtk3 qw(gtknew gtkset);
+use ugtk3 qw(:create :dialogs :helpers :wrappers);
-use my_gtk;
+$ugtk3::wm_icon = "/usr/share/mcc/themes/default/drakperm-mdk.png";
+require_root_capability();
-use interactive;
-
-my $in = 'interactive'->vnew('su', 'default');
-local $_ = join '', @ARGV;
+#- vars declaration
+my ($level) = chomp_(`cat /etc/sysconfig/msec | grep SECURE_LEVEL= |cut -d= -f2`);
+my $default_perm_level = "level " . $level;
+my %perm_files = ($default_perm_level => '/usr/share/msec/perm.' . $level,
+ 'editable' => '/etc/security/msec/perm.local',
+ );
-/-h/ and die N("no help implemented yet.\n");
-/-version/ and die 'version: $Id$'."\n";
+my %perm_l10n = ($default_perm_level => N("System settings"),
+ 'editable' => N("Custom settings"),
+ 'all' => N("Custom & system settings"),
+ );
+my %rev_perm_l10n = reverse %perm_l10n;
+my ($editable, $modified) = (0, 0);
+my @rules;
-#- vars declaration
-my ($default_perm_level) = "level ".chomp_(`cat /etc/sysconfig/msec | grep SECURE_LEVEL= |cut -d= -f2`);
-my %CURENT;
-my $perm_path = '/usr/share/msec/';
-my $local_path = '/etc/security/msec/';
-my %perm = ( 'level 1' => $perm_path.'perm.1',
- 'level 2' => $perm_path.'perm.2',
- 'level 3' => $perm_path.'perm.3',
- 'level 4' => $perm_path.'perm.4',
- 'level 5' => $perm_path.'perm.5',
- 'editable'=> $local_path.'perm.local',
- );
-my $rows_cnt = 0;
-my $editable = 0;
-my $modified = 0;
-my $prec_txt = $default_perm_level;
-#my $bg = Gtk::Gdk::Color->parse_color('grey');
#- Widget declaration
-my $w = my_gtk->new('drakperm');
+my $w = ugtk3->new(N("Security Permissions"));
+$w->{rwindow}->set_size_request(620, 400) unless $::isEmbedded;
my $W = $w->{window};
-#my $W = $::isEmbedded ? new Gtk::Plug ($::XID) : new Gtk::Window ("toplevel");
-$W->signal_connect(delete_event => sub { my_gtk->exit });
-my $scroll = new Gtk::ScrolledWindow;
-my $Perm_list = new_with_titles Gtk::CList((N("path"),N("user"),N("group"),N("permissions")));
-my $vb = new Gtk::VBox(0,5);
-my $select_box= new Gtk::HBox(0,5);
-my $action_box= new Gtk::HBox(0,5);
-my $up_down_box=new Gtk::HBox(0,5);
-my $B_quit = new Gtk::Button('quit');
-my $B_sav = new Gtk::Button('save');
-my $B_up = new Gtk::Button(N("Up"));
-my $B_del = new Gtk::Button(N("delete"));
-my $B_edit = new Gtk::Button(N("edit"));
-my $B_down = new Gtk::Button(N("Down"));
-my $B_add = new Gtk::Button(N("add a rule"));
-my $label_perm= new Gtk::Label(N("select perm file to see/edit"));
-my $combo_perm= new Gtk::Combo;
-my $tips = new Gtk::Tooltips;
-my $pres = new Gtk::Label(N("Drakperm is used to see files to use in order to fix permissions, owners, and groups via msec.\nYou can also edit your own rules which will owerwrite the default rules."));
-my $F = new Gtk::Frame;
+$W->signal_connect(delete_event => sub { ugtk3->exit });
+my $model = Gtk3::ListStore->new("Gtk3::Gdk::Pixbuf", ("Glib::String") x 5);
+my $permList = Gtk3::TreeView->new_with_model($model);
+
+my $pixbuf = gtknew('Pixbuf', file => 'non-editable');
+
+my @column_sizes = (150, 100, 100, 15, -1);
+
+# TreeView layout is (Editable, Path, User, Group, Permissions, [hidden]index_id)
+$permList->append_column(Gtk3::TreeViewColumn->new_with_attributes(N("Editable"), Gtk3::CellRendererPixbuf->new, 'pixbuf' => 0));
+each_index {
+ my $col = Gtk3::TreeViewColumn->new_with_attributes($_, Gtk3::CellRendererText->new, 'text' => $::i + 1);
+ $col->set_min_width($column_sizes[$::i+1]);
+ $permList->append_column($col);
+} (N("Path"), N("User"), N("Group"), N("Permissions"));
+
+my $index = 0;
+load_perms();
+
#- widgets settings
-$combo_perm->set_popdown_strings(sort(keys %perm));
-
-$tips->set_tip($B_add,N("Add a new rule at the end"));
-$tips->set_tip($B_edit,N("Edit curent rule"));
-$tips->set_tip($B_up,N("Up selected rule one level"));
-$tips->set_tip($B_down,N("Down selected rule one level"));
-$tips->set_tip($B_del,N("Delete selected rule"));
-
-#- signal management
-$W->signal_connect(delete_event => sub { my_gtk->exit });
-$Perm_list->signal_connect( select_row => \&row_setting_data );
-#$Perm_list->signal_connect( unselect_row => sub{ undef(%CURENT)});
-$B_sav->signal_connect( clicked => \&save_perm);
-$B_quit->signal_connect( clicked => sub { my_gtk->exit });
-$B_edit->signal_connect( clicked => \&row_setting_dialog );
-$B_add->signal_connect( clicked => sub{
- $Perm_list->insert( $rows_cnt ,'');
- $Perm_list->select_row($rows_cnt , 0);
- &row_setting_dialog;
- $rows_cnt++;
- });
-$B_del->signal_connect( clicked => sub {
- $Perm_list->remove(${$CURENT{'clicked'}}{'row'});
- $rows_cnt--;
- $modified++;
- });
-$B_down->signal_connect( clicked => sub {
- my $row = ${$CURENT{'clicked'}}{'row'};
- $Perm_list->row_move($row,$row+1);
- $Perm_list->unselect_all;
- $Perm_list->select_row($row+1,0);
- $CURENT{'clicked'}{'row'} = $row+1;
- });
-$B_up->signal_connect( clicked => sub {
- my $row = ${$CURENT{'clicked'}}{'row'};
- $Perm_list->row_move($row,$row-1);
- $Perm_list->unselect_all;
- $Perm_list->select_row($row-1,0);
- $CURENT{'clicked'}{'row'} = $row-1;
- });
-my $combo_sig = $combo_perm->entry->signal_connect( changed => sub{ &display_perm($combo_perm->entry->get_text , @_)});
-$Perm_list->signal_connect( button_press_event => sub{
- $editable or return 0;
- my ($clist,$event) = @_;
- if($event->{'type'} eq '2button_press'){
- &row_setting_dialog;
- }
- } );
-
-#Viewing management
-$select_box->add($label_perm);
-$select_box->add($combo_perm);
-
-$scroll->add($Perm_list);
-$scroll->set_policy('automatic','automatic');
-
-
-$Perm_list->set_shadow_type('out');
-$Perm_list->set_column_width( 0, 150 );
-$Perm_list->set_column_width( 1, 100 );
-$Perm_list->set_column_width( 2, 100 );
-$Perm_list->set_column_width( 3, 15 );
-
-$up_down_box->add($B_up);
-$up_down_box->add($B_down);
-$up_down_box->add($B_add);
-$up_down_box->add($B_del);
-$up_down_box->add($B_edit);
-
-$action_box->add($B_sav);
-$action_box->add($B_quit);
-
-$vb->pack_start($select_box,0,0,5);
-$vb->pack_start($scroll,1,1,5);
-$vb->pack_start($up_down_box,0,0,5);
-$vb->pack_start($action_box,0,0,5);
-
-my $vb_ = new Gtk::VBox(0,5);
-$F->add($vb);
-$vb_->pack_start($pres,0,0,5);
-$vb_->pack_start($F,1,1,5);
-
-$W->add($vb_);
+my $combo_perm_value = $perm_l10n{all};
+my $combo_perm = gtknew('ComboBox', list => [ sort(values %perm_l10n) ], text_ref => \$combo_perm_value);
+
+sub add_callback() {
+ row_setting_dialog(N("Add a new rule"));
+ $modified++;
+}
+
+sub edit_callback() {
+ my (undef, $iter) = $permList->get_selection->get_selected;
+ return unless $iter;
+ row_setting_dialog(N("Edit current rule"), $iter);
+}
+
+my @buttons;
+
+sub del_callback() {
+ my ($tree, $iter) = $permList->get_selection->get_selected;
+ my $removed_idx = $tree->get($iter, 5);
+ @rules = grep { $_->{index} ne $removed_idx } @rules;
+ $tree->remove($iter);
+ sensitive_buttons(0);
+ $modified++;
+}
+
+sub move_callback {
+ my ($direction) = @_;
+ my ($model, $iter) = $permList->get_selection->get_selected;
+ return if !$iter;
+ my $path = $model->get_path($iter) or return;
+ $direction eq 'up' ? $path->prev : $path->next;
+ my $iter2 = $model->get_iter($path);
+ return if !$iter2 || $model->get($iter2, 0);
+ $model->swap($iter, $iter2);
+ $modified = 1;
+ hide_up_button_iffirst_item($path);
+ hide_down_button_iflast_item($path);
+ $permList->get_selection->select_iter($iter);
+ $permList->queue_draw;
+}
+
+$permList->signal_connect(button_press_event => sub {
+ return unless $editable;
+ my (undef, $event) = @_;
+ my (undef, $iter) = $permList->get_selection->get_selected;
+ return unless $iter;
+ row_setting_dialog(N("Edit current rule"), $iter) if $event->type eq '2button-press';
+ });
+
+
+$W->add(gtknew('VBox', spacing => 5, children => [
+ if_(!$::isEmbedded, 0, Gtk3::Banner->new('/usr/share/mcc/themes/default/drakperm-mdk.png', N("Permissions"))),
+ 0, gtknew('Label_Left', text => N("Here you can see files to use in order to fix permissions, owners, and groups via msec.\nYou can also edit your own rules which will overwrite the default rules."), alignment => [ 0.5, 0 ]),
+ 1, gtknew('VBox', border_width => 0, children => [
+ 0, gtknew('Label_Left', text => N("The current security level is %s.
+Select permissions to see/edit", $level), alignment => [ 0, 0 ]),
+ 0, gtknew('HButtonBox', layout => 'start', children => [
+ 0, $combo_perm,
+ ]),
+ 0, gtknew('Label'),
+ 1, gtknew('ScrolledWindow', child => $permList),
+ 0, my $up_down_box = gtknew('HBox', spacing => 5, children_loose => [ @buttons =
+ map {
+ gtkset_tip(
+ gtknew('Button', text => $_->[0], clicked => $_->[2]),
+ $_->[1]);
+ } ([ N("Up"), N("Move selected rule up one level"), sub { move_callback('up') } ],
+ [ N("Down"), N("Move selected rule down one level"), sub { move_callback('down') } ],
+ [ N("Add a rule"), N("Add a new rule at the end"), \&add_callback ],
+ [ N("Delete"), N("Delete selected rule"), \&del_callback ],
+ [ N("Edit"), N("Edit current rule"), \&edit_callback ]) ]),
+ 0, gtknew('VBox'),
+ ]),
+ 0, create_okcancel({
+ cancel_clicked => sub { ugtk3->exit },
+ ok_clicked => \&save_perm,
+ },
+ undef, undef, '',
+ [ N("Help"), sub { run_program::raw({ detach => 1 }, 'drakhelp', '--id', 'drakperm') } ],
+ )
+ ])
+ );
$W->show_all;
$w->{rwindow}->set_position('center') unless $::isEmbedded;
-&display_perm($default_perm_level);
-$combo_perm->entry->set_text($default_perm_level);
+display_perm('all');
+my $_combo_sig = $combo_perm->entry->signal_connect(changed => sub {
+ my $class = $rev_perm_l10n{$combo_perm_value};
+ $permList->set_reorderable($class eq 'editable');
+ display_perm($class , @_);
+ });
+
+$permList->get_selection->signal_connect('changed' => sub {
+ my ($select) = @_;
+ my (undef, $iter) = $select->get_selected;
+ return if !$iter;
+ my $locked = $model->get($iter, 0);
+ sensitive_buttons($iter ? $editable && !$locked : 0);
+ return if $locked;
+ my $curr_path = $model->get_path($iter);
+ hide_up_button_iffirst_item($curr_path);
+ hide_down_button_iflast_item($curr_path);
+ });
-#- Gtk loop start here
$w->main;
+ugtk3->exit;
-#- Should never get here
-my_gtk->exit;
+sub hide_up_button_iffirst_item {
+ my ($curr_path) = @_;
+ my $first_path = $model->get_path($model->get_iter_first);
+ $buttons[0]->set_sensitive($first_path && $first_path->compare($curr_path));
+}
-#- Built in functions
-sub check_save{
- $modified or return 0;
- my $sav_ = $in->ask_okcancel('Warning','your changed will be lost do you wish to continue?');
- $sav_
- and $modified = 0;
- return $sav_;
+sub hide_down_button_iflast_item {
+ my ($curr_path) = @_;
+ $curr_path->next;
+ my $next_item = $model->get_iter($curr_path);
+ $buttons[1]->set_sensitive($next_item && !$model->get($next_item, 0));
}
-#- Desc => set the Perm_list CList with the appropriate value
-sub display_perm{
- local $perm_level = shift @_;
- local $file = $perm{$perm_level};
- local $sav_ = &check_save;
- local $i=0;
- if($modified && ! $sav_){
- $combo_perm->entry->signal_handler_block($combo_sig);
- $combo_perm->entry->set_text($prec_txt);
- $combo_perm->entry->signal_handler_unblock($combo_sig);
- return 0;
- }
-
- $editable = ($perm_level =~ /^level \d/)?0:1;
-
- $Perm_list->clear();
- open F,$file;
- while(<F>){
- m/^([^#]\S+)\s+([^.\s]+)(\.(\S+))?\s+(\d+)/
- or next;
- @line = ( $1,
- $2,
- $4,
- $5,
- );
- $Perm_list->insert($i++,@line);
- }
- close F;
- $up_down_box->set_sensitive($editable);
-
- $rows_cnt = $i;
- $prec_txt = $perm_level;
- undef(%CURENT);
+
+sub display_perm {
+ my ($perm_level) = @_;
+ return unless $perm_level;
+ my $show_sys_rules = $perm_level eq $default_perm_level;
+ my $show_user_rules = $perm_level eq 'editable';
+ my $show_all_rules = $perm_level eq 'all';
+ # cleaner way: only remove filtered out rules, add those not any more filtered rather than refilling the whole tree
+ $model->clear;
+ foreach my $rule (@rules) {
+ next if !$show_all_rules && ($show_user_rules && $rule->{editable} || $show_sys_rules && !$rule->{editable});
+ $model->append_set(map_index { if_(defined $rule->{$_}, $::i => $rule->{$_}) } qw(editable path user group perms index));
+ }
+
+ # alter button box behavior
+ $editable = $perm_level =~ /^level \d/ ? 0 : 1;
+ $up_down_box->set_sensitive($editable);
+ sensitive_buttons(0) if $editable;
}
-#- Desc => save the perm.local file if modification made
-sub save_perm{
- $modified or return 0;
- open F, '>'.$local_path.'perm.local' or die("F CHIER BORDEL");
- for($i = 0 ; $i <= $rows_cnt;$i++){
- $line = $Perm_list->get_text( $i , 0 )."\t".$Perm_list->get_text($i,1).(($Perm_list->get_text($i,2))?".".$Perm_list->get_text($i,2):"")."\t".$Perm_list->get_text($i,3)."\n";
- print F $line ;
- }
- close F;
- $modified = 0;
+sub save_perm() {
+ my $val;
+ if ($modified) {
+ my $F;
+ open $F, '>' . $perm_files{editable} or die(qq(Impossible to process "$perm_files{editable}"));
+ $model->foreach(sub {
+ my ($model, $_path, $iter) = @_;
+ return 0 if $model->get($iter, 0);
+ my $line = $model->get($iter, 1) . "\t" . $model->get($iter, 2) . ($model->get($iter, 3) ? "." . $model->get($iter, 3) : "") . "\t" . $model->get($iter, 4) . "\n";
+ print $F $line;
+ return 0;
+ }, $val);
+ close $F;
+ }
+ $modified = 0;
+ ugtk3->exit;
}
-#- on list selection we get all data concerning the curent selection
-sub row_setting_data{
- my ( $widget, $row, $column, $event ) = @_;
- %CURENT = ( 'clicked' =>{ 'row'=> $row,
- 'col'=> $column,
- },
- 'data' =>[ $Perm_list->get_text( $row,0),
- $Perm_list->get_text( $row,1),
- $Perm_list->get_text( $row,2),
- $Perm_list->get_text( $row,3),
- ]
- );
- #print(%{$CURENT{'clicked'}});print("\n");
+
+sub load_perms() {
+ foreach my $file (@perm_files{($default_perm_level, 'editable')}) {
+ my @editable = if_($file ne $perm_files{editable}, editable => $pixbuf);
+ local $_;
+ foreach (cat_($file)) {
+ next if /^#/;
+ # Editable, Path, User, Group, Permissions
+ if (m/^(\S+)\s+([^.\s]+)\.(\S+)?\s+(\d+)/) {
+ push @rules, { @editable, path => $1, user => $2, group => $3, perms => $4, index => $index };
+ } elsif (m/^(\S+)\s+current?\s+(\d+)/) {
+ push @rules, { @editable, path => $1, user => 'current', group => '', perms => $2, index => $index };
+ } else {
+ warn qq(unparsable "$_"line);
+ }
+ $index++;
+ }
+ }
}
-#- Desc => Here is the complete subwindow for rule settings
-sub row_setting_dialog{
-
- $editable or return 0;
-
- my $row = ${$CURENT{'clicked'}}{'row'};
-
- #- dlg widgets declaration
- my $dlg = new Gtk::Dialog();
- my $ok = new Gtk::Button('ok');
- my $cancel = new Gtk::Button('cancel');
- my $browse = new Gtk::Button(N("browse"));
- my $users = new Gtk::Combo;
- my $groups = new Gtk::Combo;
- my $file = new Gtk::Entry;
- my $file_hbox=new Gtk::HBox(0,5);
- my $usr_hbox= new Gtk::HBox(0,5);
- my $usr_vbox= new Gtk::VBox(0,5);
- my $usr_check=new Gtk::CheckButton(N("Current user"));
- local @rights = ('user','group','other');
- local @check = ( '' , 'read','write','execute');
- my $hb_rights = new Gtk::HBox(0,15);
- my $vb_rights = new Gtk::VBox(0,15);
- my $F_rights = new Gtk::Frame(N("Permissions"));
- my $F_path = new Gtk::Frame(N("Path"));
- my $F_usr = new Gtk::Frame(N("Property"));
- my $vb_specials = new Gtk::VBox(0,5);
- my $sticky = new Gtk::CheckButton(N("sticky-bit"));
- my $suid = new Gtk::CheckButton(N("Set-UID"));
- my $gid = new Gtk::CheckButton(N("Set-GID"));
- local $rght = ${$CURENT{'data'}}[3];
- local $s = (length($rght) == 4)?substr($rght,0,1):0 ;
- local $user = ($s)?substr($rght,1,1):substr($rght,0,1);
- local $group = ($s)?substr($rght,2,1):substr($rght,1,1);
- local $other = ($s)?substr($rght,3,1):substr($rght,2,1);
- foreach(@check){
- $vb_rights->add(new Gtk::Label($_));
- }
- $hb_rights->add($vb_rights);
- foreach $r (@rights){
- %{"$r"} = &get_right(${"$r"});
- ${'_vb'.$r} = new Gtk::VBox(0,5);
- ${'_vb'.$r}->add(new Gtk::Label($r));
- foreach my $c (@check){
- $c eq '' and next;
- ${"$r"."_$c"} = new Gtk::CheckButton;
- ${"$r"}{$c}
- and ${"$r"."_$c"}->set_active(1);
- ${"_vb$r"}->add(${"$r"."_$c"});
- }
- $hb_rights->add(${'_vb'.$r});
- }
-
- $vb_specials->add(new Gtk::Label(' '));
- $vb_specials->add($suid);
- $vb_specials->add($gid);
- $vb_specials->add($sticky);
- $hb_rights->add($vb_specials);
-
- #- dlg widgets settings
- local %s_right = &get_right($s);
- $s_right{'execute'} and $sticky->set_active(1);
- $s_right{'write'} and $gid->set_active(1);
- $s_right{'read'} and $suid->set_active(1);
-
- $file->set_text(${$CURENT{'data'}}[0]);
-
- $users->set_popdown_strings(&get_user_or_group('users'));
- $users->entry->set_text(${$CURENT{'data'}}[1]);
- $users->entry->set_editable(0);
-
- $groups->set_popdown_strings(&get_user_or_group);
- $groups->entry->set_text(${$CURENT{'data'}}[2]);
- $groups->entry->set_editable(0);
- $dlg->set_policy(0,0,1);
- $dlg->set_modal(1);
-
-
- if( ${$CURENT{'data'}}[1] eq 'current'){
- $usr_check->set_active(1);
- $groups->set_sensitive(0);
- $users->set_sensitive(0);
- }
-
- $tips->set_tip($sticky,N("Used for directory:\n only owner of directory or file in this directory can delete it"));
- $tips->set_tip($suid,N("Use owner id for execution"));
- $tips->set_tip($gid,N("Use group id for execution"));
- $tips->set_tip($usr_check,N("when checked, owner and group won't be changed"));
-
- #- event management
- $cancel->signal_connect( clicked =>sub{ $dlg->destroy } );
- $browse->signal_connect( clicked => sub {
- my $file_dlg = new Gtk::FileSelection(N("Path selection"));
- $file_dlg->set_modal(1);
- $file_dlg->show;
- $file_dlg->set_filename( $file->get_text );
- $file_dlg->cancel_button->signal_connect( clicked => sub{ $file_dlg->destroy });
- $file_dlg->ok_button->signal_connect( clicked => sub{
- $file->set_text($file_dlg->get_filename);
- $file_dlg->destroy;
- });
-
- });
- $ok->signal_connect( clicked => sub{
- $Perm_list->set_text($row,0,$file->get_text);
- if($usr_check->get_active){
- $Perm_list->set_text($row,1,'current');
- $Perm_list->set_text($row,2,'');
- }else{
- $Perm_list->set_text($row,1,$users->entry->get_text);
- $Perm_list->set_text($row,2,$groups->entry->get_text);
- }
- #- mod calculation
- $user = ($user_read->get_active?4:0)+($user_write->get_active?2:0)+($user_execute->get_active?1:0);
- $group = ($group_read->get_active?4:0)+($group_write->get_active?2:0)+($group_execute->get_active?1:0);
- $other = ($other_read->get_active?4:0)+($other_write->get_active?2:0)+($other_execute->get_active?1:0);
- $s = ($sticky->get_active?1:0)+($suid->get_active?4:0)+($gid->get_active?2:0);
- $Perm_list->set_text($row,3,(($s)?$s:'').$user.$group.$other);
- $dlg->destroy;
- $modified++;
- });
- $usr_check->signal_connect( clicked => sub {
- if($usr_check->get_active){
- $groups->set_sensitive(0);
- $users->set_sensitive(0);
- }else{
- $groups->set_sensitive(1);
- $users->set_sensitive(1);
- }
- });
-
- #- dlg widgets placement
- $file_hbox->add($file);
- $file_hbox->add($browse);
-
- $usr_vbox->add($usr_check);
- $usr_vbox->add($usr_hbox);
-
- $usr_hbox->add(new Gtk::Label(N("user :")));
- $usr_hbox->add($users);
- $usr_hbox->add(new Gtk::Label(N("group :")));
- $usr_hbox->add($groups);
-
- $F_path->add($file_hbox);
- $F_rights->add($hb_rights);
- $F_usr->add($usr_vbox);
-
- $dlg->vbox->add($F_path);
- $dlg->vbox->add($F_usr);
- $dlg->vbox->add($F_rights);
-
- $dlg->action_area->add($ok);
- $dlg->action_area->add($cancel);
-
- $dlg->show_all;
+sub row_setting_dialog {
+ my ($title, $o_iter) = @_;
+
+ my $dlg = gtknew('Dialog', transient_for => $w->{real_window}, title => $title);
+# $dlg->set_resizable(0);
+ my $browse = gtknew('Button', text => N("browse"));
+ my $file = gtknew('Entry', $o_iter ? (text => $model->get($o_iter, 1)) : ());
+ my ($other, $group, $user, $s) = $o_iter ? reverse(split(//, $model->get($o_iter, 4))) : ();
+ my @bits = qw(sticky gid suid);
+ my @rights = qw(read write execute);
+ my @owners = (N_("user"), N_("group"), N_("other"));
+
+ my %rights = (user => $user, group => $group, other => $other);
+ my %rights_labels = (user => N("User"), group => N("Group"), other => N("Other"));
+ my %checks = ('read' => {
+ label => N("Read"),
+ tip => { map { $_ =>
+ #-PO: here %s will be either "user", "group" or "other"
+ N("Enable \"%s\" to read the file", translate($_));
+ } keys %rights },
+ },
+ 'write' => {
+ label => N("Write"),
+ tip => { map { $_ =>
+ #-PO: here %s will be either "user", "group" or "other"
+ N("Enable \"%s\" to write the file", translate($_));
+ } keys %rights },
+ },
+ 'execute' => {
+ label => N("Execute"),
+ tip => { map { $_ =>
+ #-PO: here %s will be either "user", "group" or "other"
+ N("Enable \"%s\" to execute the file", translate($_));
+ } keys %rights },
+ },
+ sticky => { label => N("Sticky-bit"), tip => N("Used for directory:\n only owner of directory or file in this directory can delete it") },
+ suid => { label => N("Set-UID"), tip => N("Use owner id for execution") },
+ gid => { label => N("Set-GID"), tip => N("Use group id for execution") },
+ );
+
+ #- dlg widgets settings
+ my %s_right = get_right($s);
+
+ my $alrd_exsts = defined $o_iter;
+
+ my $users = gtknew('ComboBox', list => [ my @users = get_user_or_group('users') ]);
+ $users->entry->set_text($model->get($o_iter, 2)) if $o_iter;
+ $users->set_wrap_width(3);
+
+ my $groups = gtknew('ComboBox', list => [ my @groups = get_user_or_group('groups') ]);
+ $groups->entry->set_text($model->get($o_iter, 3)) if $o_iter;
+ $groups->set_wrap_width(3);
+
+ my $id_box = gtknew('Table', homogeneous => 0, xpadding => 0.1, ypadding => 0, border_width => 0, children => [
+ [ gtknew('Label_Left', text => N("User:")), $users ],
+ [ gtknew('Label_Left', text => N("Group:")), $groups ],
+ ]
+ );
+
+ my $usr_check = gtksignal_connect(gtkset_tip(gtknew('CheckButton', text => N("Current user")),
+ N("When checked, owner and group will not be changed")),
+ clicked => sub { $id_box->set_sensitive(!$_[0]->get_active) });
+
+ if ($o_iter && $model->get($o_iter, 2) eq 'current') {
+ $usr_check->set_active(1);
+ $id_box->set_sensitive(0);
+ } else { $usr_check->set_active(0) }
+
+
+ $browse->signal_connect(clicked => sub {
+ my $file_dlg = gtknew('FileChooserDialog', title => N("Path selection"), action => 'select_folder',
+ modal => 1, transient_for => $dlg);
+ $file_dlg->set_filename($file->get_text);
+ $file_dlg->show;
+ my $answer = $file_dlg->run;
+ if ($answer eq 'ok') {
+ $file->set_text($file_dlg->get_filename);
+ }
+ $file_dlg->hide;
+ $file_dlg->destroy;
+ });
+ my %perms;
+
+ gtkpack_($dlg->get_child,
+ 0, gtknew('Title2', label => N("Path")),
+ 0, gtknew('HBox', border_width => 18, children => [
+ 1, $file,
+ 0, $browse
+ ]
+ ),
+ 0, gtknew('Title2', label => N("Property")),
+ 0, gtknew('VBox', border_width => 18, children => [
+ 0, $usr_check,
+ ]
+ ),
+ 0, $id_box,
+ 0, gtknew('Title2', label => N("Permissions")),
+ 1, gtknew('HBox', border_width => 0, children_loose => [
+ gtknew('VBox', border_width => 0, children_loose => [
+ gtknew('Label', text => ""),
+ map { gtknew('Label_Left', text => $checks{$_}{label}, alignment => [ 0, 0 ]) } @rights,
+ ]),
+ (map {
+ my $owner = $_;
+ $perms{$owner} = { get_right($rights{$owner}) };
+ my $vbox = gtknew('VBox', children_loose => [
+ gtknew('Label', text => $rights_labels{$owner}),
+ map {
+ my $c = $_;
+ my $active = $perms{$owner}{$c};
+ $perms{$owner}{$c} = gtkset_tip(gtknew('CheckButton'),
+ $checks{$c}{tip}{$owner},
+ );
+ gtkset_active($perms{$owner}{$c}, $active);
+ } @rights,
+ ]);
+
+ $vbox;
+ } @owners),
+ gtknew('VBox', children_loose => [
+ gtknew('Label', text => ' '),
+ map { $perms{$_} = gtkset(gtknew('CheckButton', text => $checks{$_}{label}), tip => $checks{$_}{tip}) } @bits,
+ ]),
+ ]),
+ );
+ $perms{sticky}->set_active($s_right{execute});
+ $perms{gid}->set_active($s_right{write});
+ $perms{suid}->set_active($s_right{read});
+
+ gtkadd($dlg->get_action_area,
+ create_okcancel(my $w =
+ {
+ cancel_clicked => sub { $dlg->destroy },
+ ok_clicked => sub {
+ my ($path, $user, $group, $perms, $_idx);
+ $path = $file->get_text;
+ if ($path !~ m!^/!) {
+ err_dialog(N("Warning"), N("The first character of the path must be a slash (\"/\"):\n\"%s\"", $path));
+ return 1;
+ }
+ if ($usr_check->get_active) {
+ $user = 'current';
+ $group = '';
+ } else {
+ $user = $users->entry->get_text;
+ $group = $groups->entry->get_text;
+ if (!member($user, @users) || !member($group, @groups)) {
+ err_dialog(N("Warning"), join("\n", N("Both the username and the group must valid!"),
+ N("User: %s", $user),
+ N("Group: %s", $group),
+ )
+ );
+ return 1;
+ }
+ }
+ $perms = sprintf("%03o", eval(join('', "0b",
+ (map { $perms{$_}->get_active || 0 } reverse @bits),
+ (map { my $owner = $_;map_index {
+ $perms{$owner}{$_}->get_active || 0;
+ } @rights } @owners))));
+ # create new item if needed (that is when adding a new one) at end of list
+ if (!$o_iter) {
+ $o_iter = $model->append;
+ push @rules, { path => $path, user => $user, group => $group, perms => $perms, index => $index };
+ $model->set($o_iter, 5 => $index++);
+ }
+ $model->set($o_iter, 1 => $path, 2 => $user, 3 => $group, 4 => $perms);
+ $dlg->destroy;
+ $modified++;
+ }
+ },
+ ),
+ );
+
+ $w->{ok}->set_sensitive(!$model->get($o_iter, 0)) if $alrd_exsts;
+ $dlg->show_all;
}
-#- Desc => return an array of the available users on the machine
-sub get_user_or_group{
- my $what = @_;
- local @users;
- $what eq 'users'
- and open F,'/etc/passwd'
- or open F, '/etc/group';
-
- while(<F>){
- m/^([^#:]+):[^:]+:[^:]+:/
- or next;
- push @users,$1;
- }
- close F;
- return sort(@users);
+sub get_user_or_group {
+ my ($what) = @_;
+ my @users;
+
+ local $_;
+ my $is_users = $what eq 'users';
+ foreach (cat_($is_users ? '/etc/passwd' : '/etc/group')) {
+ if ($is_users) {
+ push @users, $1 if m/^([^#:]+):[^:]+:[^:]+:/; # or next;
+ } else {
+ push @users, $1 if m/^([^#:]+):[^:]*:[^:]*:/; # or next;
+ }
+ }
+ return sort(@users);
}
-#- Desc => return hash of boolean value for read write and execution permission from a value between 0 - 7
-sub get_right{
- my $right = shift @_;
- my %rght = ('read'=>0,'write'=>0,'execute'=>0);
- ($right - 4) >= 0
- and $rght{'read'}=1
- and $right = $right-4;
- ($right - 2) >= 0
- and $rght{'write'}=1
- and $right = $right-2;
- ($right - 1) >= 0
- and $rght{'execute'}=1
- and $right = $right-1;
- return %rght;
+sub get_right {
+ my ($right) = @_;
+ my %rght = ('read' => 0, 'write' => 0, 'execute' => 0);
+ $right - 4 >= 0 and $rght{read}=1 and $right = $right-4;
+ $right - 2 >= 0 and $rght{write}=1 and $right = $right-2;
+ $right - 1 >= 0 and $rght{execute}=1 and $right = $right-1;
+ return %rght;
}
+sub sensitive_buttons {
+ foreach my $i (0, 1, 3, 4) {
+ $buttons[$i]->set_sensitive($_[0]);
+ }
+}